虽然您可以完全使用Java编写应用程序,但有些情况下Java本身并不能满足您的应用程序的需求。当应用程序不能完全用Java编写时,程序员使用JNI编写Java本机方法来处理这些情况。
以下示例说明何时需要使用Java本机方法:
- 标准Java类库不支持应用程序所需的与平台相关的功能。
- 您已经有一个用另一种语言编写的库,并希望通过JNI使其可以访问Java代码。
- 您希望在较低级别的语言(如汇编语言)中实现一小部分时间关键代码。
来源:https://docs.oracle.com/javase/1 ... ec/intro.html#wp725
了解JNI函数
JNI函数就是在native层定义的本地函数,对应于在java层使用native关键字声明的方法的。直白的说,就是在Java层声明,C/C++语言实现的。当然,这个函数并不一般,它会通过JNI某种机制与Java层的方法进行关联,使得Java层代码可以很方便的调用它。
jni函数的语法和调用规则
- 将java语言的数据类型转换成底层语言调用规则
- 将java语言的方法调用转换成底层语言函数或方法
jni数据类型的转化
jni在java和C之间建立连接,因此jni首先要统一两者的数据类型Java Type
| Native Type
| Description
| boolean
| jboolean
| unsigned 8 bits
| byte
| jbyte
| signed 8 bits
| char
| jchar
| unsigned 16 bits
| short
| jshort
| signed 16 bits
| int
| jint
| signed 32 bits
| long
| jlong
| signed 64 bits
| float
| jfloat
| 32 bits
| double
| jdouble
| 64 bits
| void
| void
| N/A
|
The following definition is provided for convenience. #define JNI_FALSE 0 #define JNI_TRUE 1
The jsize integer type is used to describe cardinal indices and sizes: typedef jint jsize;
java中可以直接调用底层语言的函数,jni规定了java调用底层语言的方法签名
java中有重载概念,所以java方法转换成签名,签名再转化为函数Type Signature | Java Type | Z
| boolean
| B
| byte
| C
| char
| S
| short
| I
| int
| J
| long
| F
| float
| D
| double
| L fully-qualified-class ;
| fully-qualified-class
| [ type
| type[]
| ( arg-types ) ret-type
| method type
|
For example, the Java method: long f (int n, String s, int[] arr);
has the following type signature: (ILjava/lang/String;[I)J
jni机制实现
native 声明的函数可以不实现
class Cls {
native double f(int i, String s); // 声明为本地方法
static {
System.loadLibrary(“库名”); // 通过静态初始化语句块来加载动态库
}
}
程序实现测试java代码
javah -jni Hello 生成Hello .h
打开Hello .h 文件里面已经写好C函数的名字
C代码
将C文件制做成共享库.so,注意指定jni.h和jni_md.h文件路径
gcc -shared -fPIC hello.c -o libhello.so -I /usr/java/jdk1.6.0_45/include/ -I /usr/java/jdk1.6.0_45/include/linux/
java Hello 运行程序实验现象
|