自 Java 语言中调用 NAG 算法库
NAG 技术报告 TR 2/09
Numerical Algorithms Group, April 2009摘要
本报告将完整说明如何在 Java 语言中调用 NAG C 及 NAG Fortran 算法库中的函数。 我们同时以 UNIX 及 Microsoft Windows 平台的环境进行说明。
内容
NAG C 算法库 [1] 与 NAG Fortran 算法库 [2] 包含了许多的数学 与统计函数。包含了线性代数、优化、积分、微分方程、回归分析与时间序列等。虽然他们都是由 C 或 Fortran 语言所撰写,但是这些函数是可以被 各种不同的语言所调用使用的,例如:C++ 等。在 PC 环境中,NAG 的 DLL 算法库也能以不同的方式被调用使用[3]。 很自然的,有人会问能不能在 Java[4] 语言中调用 NAG 的函数呢?
对某些需要做数值计算的人来说,第一个方式就是开发一个拥有计算功能的 Java 类别库,这样需要开发新的程序代码, 在 Java Grande Forum 的 Numerics Working Group 中便有完整的说明,其中有些是新撰写的 Java 程序、有些则是转换不同语言的程序代码。 JavaNumerics 网页 [5] 提供了许多有用的资讯,包含了因为 Java 本身的限制,对使用 Java 从事数值计算所会遇到困难的探讨。
在本报告中,我们采用另一个方法,在 Java 程序中调用 NAG 算法库,因此规避了重新开发程序以及测试的问题,因为我们意在调用 NAG 算法库, 所以开发出来的这个应用系统不再是跨平台的,不像是完全由 Java 所开发的语言特性;因为在进行数值计算时会仰赖 NAG 算法库,而它并非跨平台的文件。 然而,在某种意义上来说,这样的应用系统依然是 可携 的,因为 NAG 算法库在各种不同的环境中都能够支持。
除了不需要重头撰写 Java 的数值函数外,采用 NAG 算法库还有另一项优势。Java 语言原先的设计是可以跨平台的,编译过的程序可以在任何有 虚拟机 (VM) 的环境中运行。为了能够达成这样的功能, Java 编译器并不会将程序编译成与机器相依的代码,例如传统语言 C 或 C++ 的方式;而是编译成与机器不相关的 byte code。这个 byte code 将会在运行期中 被虚拟机所转译。虽然 Java 直译器是相当有效率的,但很明显的它的运行速度将不会如同其他已经转换为汇编语言的程序一样快。 对某些应用系统来说,这也许并不重要,但对于需要大量处理器计算的应用程序来说,就显得极为重要了。 将这些需要进行计算的部分移到 Java 外,采用 NAG 算法库运行,我们可以预期的到,它能减少许多数值计算的时间。
为了要能够在 Java 程序中使用 NAG 算法库,我们需要使用 Java Native Interface。
2. Java Native Interface (JNI)
Java Native Interface (JNI),是 Java Software Development Kit (SDK) 的一部份,提供想要在 Java 程序中调用 其他程序语言 所需要的 编译期与运行期支持。我们所谓的 其他程序语言,指的是非 Java 的程序,通常是 C 或者 C++;本报告中我们泛指 C 语言。
在编译期中,JNI 定义了 Java 与 C 语言相对应的数据型别 - C 程序可以在 JNI 的头文件中取得这样的资讯。 javah 是 Java SDK 中所提供的程序,能够协助特定的头文件,藉以消除 Java 与 C 语言函数间沟通所可能产生的错误。
在运行期,JNI 允许 Java 将其对象传递至 C 程序中,也允许 C 程序读取 Java 的属性 与 方法。也就是说, C 程序能够设定 Java 类别的属性,也能够在 C 语言中调用 Java 的方法。
在撰写本篇报告时,我们是在以下的环境中进行示例程序的测试:
- Linux 环境,运行 64-bit Fedora 8 (Werewolf) 操作系统以及 Java SE Development Kit 1.6.0u11,以及 gcc (GCC) 4.5.0,与 NAG C 算法库第 9 版,NAG Fortran 算法库第 22 版
- 运行 Windows XP 以及 Java SE Development Kit v1.6.0u11,以及 Microsoft Visual C++ version 9.0 与 NAG C 算法库第 9 版,NAG Fortran 算法库第 22 版
在其他 UNIX 平台上的操作应该类似于 Linux x86 环境;其中主要的差别在于 Java include 文件的路径,以及编译动态链接文件的方法。
您可以参考 Sun Microsystems 的网站 [6],提供了相当多完整的 Java Native Interface 说明与介绍。
使用 JNI,必须要透过中间层的共享算法库 (UNIX 系统) 或者 DLL (Windows 系统)。这个动态链接库是作为 Java 语言与 NAG C 算法库沟通的桥梁。
接口库是相当重要的,当外部的原始方法 (函数 或 子程序) 被 Java 调用时,额外的参数将会被附加到原先的参数列中被传递。 这些附加的参数让外部程序能够取得 Java 的方法及属性等资讯,当然,NAG 算法库原先并未设计用来处理这些参数。 此外,从 Java 传递的参数型别并不与标准 C 或 Fortran 语言的数据型别一致,所以 NAG 算法库并不能直接使用。 接口库必须能够处理这些问题,让 NAG 算法库能够被调用,且能将结果正确的传回 Java 程序中。
Java Native Interface 链接了 Java 与 NAG 算法库
实现自 Java 调用 NAG 算法库,需要三个步骤
- 在 Java 中先进行声明。声明中须包含 native,用来表示将由外部来实现 Java 编译器。
- 设计由 C 语言所使用的 header 文件。本文件会包含原始方法的定义,也就是说,它会包含 C 函数所需额外的参数,以便于存取 Java 方法及其 属性,而且也同时定义标准 C 型态的参数型别。
- 在 C 语言中实现调用函数。此函数将会使用以上所生成的 header 文件,并调用 NAG C 或 Fortran 算法库,也许会返回至 Java 方法或传回结果至 Java 程序中。 C 程序将会被编译成接口库 (interface library)。 请您注意,我们都是以 C 语言撰写接口,即便我们也用来调用 NAG Fortran 算法库。那是因为先前我们提到额外参数的结构是不容易在 Fortran 语言中实现。
当界面库已经生成好后,使用它的 Java 程序仍旧是跨平台的,虽然它本身并不是。也因此,我们必须要生成不同平台的接口库 (interface library),但是不需要重新编译 Java 程序。
透过示例,您可以很容易的了解到生成接口是一个简易的流程。我们提供了六个例子,每一个皆提供不同的 JNI 与 NAG 算法库的操作方式。
4.1 示例 1
Bessel 函数Y0 (x)
|
这是最简单的一个例子:调用 NAG C s17acc 函数并仅传回单一数值 - Y0 (x) Bessel 函数。 并不需要任何额外程序处理其他数据。 |
4.2 示例 2 求解线性方程 A x = b
|
调用求解线性方程函数 f04arc,并传回数组结果。需要自 Java 中取得输入数据,并将 C 语言的结果传回至 Java 中。 |
4.3 示例 3 求解用户定义函数 f(x) 的积分
|
我们调用 NAG C 算法库中的 d01ajc 函数,它需要输入一个被积函数。我们演示如何利用 C 程序调用 Java 的被积分函数。同时您也可以了解 C 程序如何能将结果传回至 Java 中。 |
4.4 示例 4 求解非线性最小化问题
|
本示例说明如何调用 NAG Fortran 算法库中的非线性最小化函数 e04ucf。C 语言的接口程序需要处理 Fortran 函数的调用,而且必须处理自 Fortran 返回至 C 然后到 Java 的函数。 同时 Fortran 必须储存二维矩阵。 |
4.5 示例 5 以 Black–Scholes–Merton 公式计算欧式选择权
|
另一个示例传回矩阵结果,选择权函数 s30aac。 |
4.6 示例 6 求解全局优化问题
|
演示如何调用 NAG Fortran 算法库的全局优化函数 e05jbf。 |
如果您已经充分了解以上示例,您已经具备了在 Java 语言中传递数据到 NAG C 与 Fortran 算法库中的技术。 您应该能够使用这些技能,您也可以使用这些例子开发不同的接口,调用其他的 NAG 函数,例如:可以设计若 NAG 函数调用失败时,传回错误讯息到 Java 程序中, 取代原先只传回整数码。
如果您对在 Java 语言中调用 NAG Fortran 函数深感兴趣,NAG 提供的 header files [7] 可以帮助您更快速的 在 C 程序中调用 NAG Fortran 函数。
您可以下载以上示例中的原始程序,还有另外的选择权定价程序。
调用 NAG Fortran 算法库函数:fortran_examples.zip
调用 NAG C 算法库函数:c_examples.zip
- [1] NAG C 算法库使用手册
Numerical Algorithms Group
Numerical Algorithms Group Limited, Oxford, UK, 2009.
http://cn.nag-gc.com/numeric/CL/CLdocumentation.asp - [2] NAG Fortran 算法库使用手册
Numerical Algorithms Group
Numerical Algorithms Group Limited, Oxford, UK, 2009.
http://cn.nag-gc.com/numeric/FL/FLdocumentation.asp - [3] 强化应用程序中的数值功能
Numerical Algorithms Group
Numerical Algorithms Group Limited, Oxford, UK, 2004.
http://cn.nag-gc.com/numeric/Num_DLLhelp.asp - [4] Java 2 Platform, Standard Edition (J2SE) Documentation
Sun Microsystems
Sun Microsystems Inc. 1995-2004
http://java.sun.com/docs - [5] JavaNumerics
Ron Boisvert, Roldan Pozo
Java Numerics Working Group, 1998-2003.
http://math.nist.gov/javanumerics/ - [6]Java Native Interface: Programmer's Guide and Specification
Sheng Liang
Sun Microsystems Inc. 2002.
http://java.sun.com/docs/books/jni/ - [7] 在 C 语言程序中,使用 NAG C Header 文件调用 NAG Fortran 算法库
Ian Hounam
Numerical Algorithms Group Ltd, Oxford, UK, 2002
http://cn.nag-gc.com/downloads/chdownloads.asp
Copyright 2009 Numerical Algorithms Group
[NP3671]





