如何用JNI技术提高Java的性能详解
阻碍Java获得广泛应用的一个主要因素是Java程序的运行效率。Java是介于解释型和编译型之间的一种语言,同样的程序,如果用编译型语言C来实现,其运行速度一般要比Java快一倍以上。Java具有平台无关性,这使人们在开发企业级应用的时候总是把它作为主要候选方案之一,但是性能方面的因素又大大削弱了它的竞争力。为此,提高Java的性能就显得十分重要。
问题的提出
Sun公司及Java的支持者们为提高Java的运行速度已经做出了许多努力,其中大多数集中在程序设计的方法和模式选择方面。由于算法和设计模式的优化是通用的,对Java有效的优化算法和设计模式,对其他编译语言也基本同样适用,因此不能从根本上改变Java程序与编译型语言在执行效率方面的差异。
JIT(Just In Time,及时编译)技术是个比较好的思想。它的基本原理是:首先通过Java编译器把Java源代码编译成平台无关的二进制字节码。然后在Java程序真正执行之前,系统通过JIT编译器把Java的字节码编译为本地化机器码。最后,系统执行本地化机器码,节省了对字节码进行解释的时间。这样做的优点是大大提高了Java程序的性能,缩短了加载程序的时间;同时,由于编译的结果并不在程序运行间保存,因此也节约了存储空间。缺点是由于JIT编译器对所有的代码都想优化,因此同样也占用了很多时间。
动态优化技术是提高Java性能的另一个尝试。该技术试图通过把Java源程序直接编译成机器码,以充分利用Java动态编译和静态编译技术来提高Java的性能。该方法把输入的Java源码或字节码转换为经过高度优化的可执行代码和动态库 (Windows中的. dll文件或Unix中的. so文件)。该技术能大大提高程序的性能,但却破坏了Java的可移植性。
JNI技术
实际上,有一种通常为我们忽视的技术可以在很大程度上解决这个难题,那就是JNI(Java Native Interface, Java本地化方法)。主张采用纯Java的人们通常反对本地化代码的使用,他们认为在Java程序执行的过程中调用C/C++程序会影响程序的可移植性和安全性。还有一些人认为JNI只是对过去混合编程技术的简单扩展,其实际目的是为了充分利用大量原有的C程序库。
其实,我们不必拘泥于严格的平台独立性限制,因为采用JNI技术只是针对一些严重影响Java性能的代码段,该部分可能只占源程序的极少部分,所以几乎可以不考虑该部分代码在主流平台之间移植的工作量。同时,也不必过分担心类型匹配问题,我们完全可以控制代码不出现这种错误。此外,也不必担心安全控制问题,因为Java安全模型已扩展为允许非系统类加载和调用本地方法。根据Java规范,从JDK 1. 2开始,FindClass将设法找到与当前的本地方法关联的类加载器。如果平台相关代码属于一个系统类,则无需涉及任何类加载器; 否则,将调用适当的类加载器来加载和链接已命名的类。换句话说,如果在Java程序中直接调用C/C++语言产生的机器码,该部分代码的安全性就由Java虚拟机控制。
JNI实现步骤
编写JNI代码的大致流程如下图所示:
JNI实现流程图
1. 首先编写需要JNI功能的Java类源文件。其中,需要JNI实现的方法应当用native关键字声明。在该类中,用System. loadLibrary()方法加载需要的动态链接库。关键代码如下:
//Compute.java
……
public class Compute {
public native double comp (double [] params);
……
static {
// 调用动态链接库
System. loadLibrary(“mathlib”);
}
……
}
2. 将该类源文件用Java类编译器编译成二进制字节码文件。由于采用了native关键字声明,编译器会忽视没有代码体的JNI方法部分。
3. 利用javah -jni *.class 生成相关JNI方法的头文件。我们可以手工生成该文件,但是由于Java虚拟机是根据一定的命名规范完成对JNI方法的调用,所以手工编写头文件需要特别小心。
上述文件产生的头文件部分代码如下:
//Compute. h
……
extern “C” {
JNIEXPORT jdouble JNICALL Java_Compute_comp (JNIEnv *, jobject, jdoubleArray);
}
……
可以看出,JNI函数名称分为三部分:首先是Java关键字,供Java虚拟机识别;然后是调用者类名称(全限定的类名,其中用下划线代替名称分隔符);最后是对应的方法名称,各段名称之间用下划线分割。
JNI函数的参数也由三部分组成: 首先是JNIEnv *,是一个指向JNI运行环境的指针;第二个参数随本地方法是静态还是非静态而有所不同——非静态本地方法的第二个参数是对对象的引用,而静态本地方法的第二个参数是对其 Java 类的引用; 其余的参数对应通常 Java 方法的参数,参数类型需要根据一定规则进行映射。
4. 根据头文件编写相应方法的实现代码。由于篇幅所限,具体的实现部分在此不再赘述。在编码过程中,需要注意变量的长度问题,例如Java的整型变量长度为32位,而C语言为16位,所以要仔细核对变量类型映射表,防止在传值过程中出现问题。
5. 利用C/C++编译器将JNI实现代码编译成动态链接库。调用者类中需要显式调用该链接库。
在Win32环境下,可以利用Visual C ++或其他能产生DLL文件的C/C++编译器将实现代码编译成动态链接库。笔者利用的是Microsoft.NET Framework的编译器。编译指令如下,其中%Java_HOME%是笔者的jdk安装目录变量:
cl -I%Java_HOME%\include
-I%Java_HOME%\include\win32
-LD jnicomp. c -Femathlib. dll
在Sun Soloaris下,相应指令为:
cc -G -I/usr/local/java/include -I/usr/local/java/include/solaris jnicomp. c \
-o mathlib. so
注意,编译的时候需要用I指令包含必要的库文件路径。
经过上述处理,就基本上完成了一个包含本地化方法的Java类的开发。
JNI技术的应用
一些主要的Java技术,如JDBC和RMI,大部分都采用JNI方式实现。但是,采用JNI确实会影响程序的平台无关性,所以只能在特别需要的地方才能使用。通常来说,如果遇到下面的情况,我们可以考虑JNI:
● 需要直接操作物理设备,而没有相关的驱动程序,这时候我们可能需要用C甚至汇编语言来编写该设备的驱动,然后通过JNI调用;
● 涉及大量数学运算的部分,用Java会带来些效率上的损失;
● 用Java会产生系统难以支付的开销,如需要大量网络链接的场合;
● 存在大量可重用的C/C++代码,通过JNI可以减少开发工作量,避免重复开发。
另外,在利用JNI技术的时候要注意以下几点:
● 由于Java安全机制的限制,不要试图通过Jar文件的方式发布包含本地化方法的Applet到客户端;
● 注意内存管理问题,虽然在本地方法返回 Java 后将自动释放局部引用,但过多的局部引用将使虚拟机在执行本地方法时耗尽内存;
● JNI技术不仅可以让Java程序调用C/C++代码,也可以让C/C++代码调用Java代码。
分享到:
相关推荐
总结来说,JNI技术在嵌入式软件开发中扮演了关键角色,它解决了Java性能不足的问题,允许开发者结合Java的便利性和本地代码的效率,实现了Java与本地代码的无缝集成,提升了整体系统的性能和功能。在信息家电、网络...
JNI,全称Java Native Interface,是Java平台标准的一部分,它为...总的来说,JNI技术是Java开发者必备的技能之一,尤其在需要与本地代码交互或进行性能优化时。理解并熟练掌握JNI,能够极大地扩展Java应用程序的能力。
Java G711 JNI技术详解 Java G711项目是利用JNI(Java Native Interface)技术在Java平台下实现G711音频编解码功能的解决方案。G711是一种广泛应用于语音通信的标准,包括两种编码方式:ALAW(μ-law)和ULAW(A-...
2. 提高性能:Jni可以提高Java程序的性能,因为native代码通常比Java代码更快。 3. 跨平台开发:Jni允许开发者在不同的平台上开发应用程序,从而实现跨平台开发。 四、Jni的应用场景 1. 数据加密:Jni可以用于...
在Android平台上,这意味着Java应用可以通过JNI与C/C++编写的.so库进行交互,以此提高性能或者访问特定硬件资源。 **2.2 .so库的入口函数** 当Dalvik虚拟机执行到`System.loadLibrary()`方法时,会尝试加载指定的....
### 有关Java JNI详解 #### 一、JNI概述与重要性 Java Native Interface(JNI)是一种重要的技术,它允许Java代码与其他语言(主要是C和C++)编写的代码进行交互。这种交互能力使得开发者能够在利用Java平台的强大...
### Java的JNI跨平台技术详解 #### 一、引言 随着互联网技术的快速发展与广泛应用,跨平台服务的需求日益增长。为了满足这一需求,许多网络服务商开始开发自己的网络服务(Web Service),以抢占逐渐明晰的面向...
标题“Java通过JNI查看Windows的CPU利用率的问题”涉及到的是Java编程语言如何利用Java Native Interface (JNI) 这一技术来获取Windows操作系统的CPU使用情况。JNI是Java平台标准的一部分,它允许Java代码和其他语言...
### Java JNI 技术文档教程知识点详解 #### 一、JNI技术概述 **Java Native Interface (JNI)** 是Java平台的一项强大特性,它允许Java应用程序调用用其他编程语言(如C或C++)编写的本地代码,同时也支持从这些...
Java本地调用JNI(Java Native Interface)是一种技术,允许Java代码与用其他编程语言(如C和C++)编写的代码进行交互。自Java 1.1以来,JNI已成为Java平台的标准组成部分,主要目的是实现Java代码与其他语言的互...
由于C/C++在系统级编程上的广泛使用,JNI的出现极大地拓宽了Java应用的边界,使得Java应用能够更加灵活地利用底层资源,提高性能。 #### 三、JNI的应用场景与优势 1. **C/C++库集成**:在Java项目中集成C/C++库,...
### Java与JNI交互详解:基于“Java中使用Jni简单示例过程”的深入解析 #### 核心概念:Java Native Interface (JNI) Java Native Interface(JNI)是Java平台标准的一部分,它允许Java代码与其他语言(如C或C++)...
- **示例**:游戏引擎或嵌入式系统中,为了提高灵活性和易用性,可以选择使用Java进行某些部分的开发,并通过JNI调用Java代码。 ##### 3. 实现Java虚拟机 - **应用场景**:对于虚拟机的开发者而言,JNI是实现Java...
通过JNI,开发者可以在Java程序中使用C/C++代码,以获得更好的性能或利用现有代码库。 2. **Java调用C/C++的步骤** - 首先,在Java类中声明一个`native`关键字修饰的方法。 - 使用`javah`命令,根据Java类生成...
3. **性能优化**:对于需要进行大量计算的任务,如图像处理或科学计算,可以使用C/C++编写这部分代码来提高性能。 #### 二、JNI数据类型和数据结构 ##### 1. 基本类型 JNI定义了一组与Java类型相对应的基本类型。...
- `jni.pdf`文档可能是对JNI技术的详细介绍,包括基本概念、API使用、实例分析等。 - `jni`文件可能包含示例代码或者更深入的教程,可以帮助读者更好地理解和实践JNI开发。 总的来说,JNI是连接Java世界与本地...
### Java与JNI结合获取系统进程...通过以上分析,我们不仅理解了如何利用JNI技术在Java环境中获取系统级信息,还深入探讨了跨语言编程的具体实现细节,这对于进一步开发高性能、功能丰富的Java应用程序具有重要意义。
JNI为Java开发者提供了一种与C/C++代码交互的有效途径,这不仅可以提高程序性能,还能利用现有的C/C++库。然而,需要注意的是,由于原生代码的非可移植性,这种方式可能会增加项目的复杂度。在实际应用中,开发者...
虽然JNI增加了跨语言调用的开销,但在某些场景下,如高性能计算或图形处理,使用JNI可以充分利用本地代码的性能优势,从而提高整体应用效率。 7. **多线程支持**: JNI支持多线程环境,每个Java线程都有其对应的`...
### JNI技术手册:C/C++与Java互调详解 #### 一、JNI技术概览 **JNI(Java Native Interface)** 是Java平台的一部分,它允许Java代码与其他语言写的代码进行交互,尤其是C和C++。JNI是Java与本地代码之间沟通的...