JNI可以实现Java调用本地库,也可以实现C/C++调用Java代码。使Java使用更加灵活。
本文涉及到的一些功能:
- 创建虚拟机
- 寻找class对象,创建对象
- 调用静态方法和成员方法
- 获取成员属性,修改成员属性
C/C++调用Java代码的一般步骤:
- 编写Java代码,并编译
- 编写C/C++代码
- 配置lib进行编译,配置PATH添加相应的dll或so并运行
编写Java代码并编译
JNITest代码仅仅有静态方法和成员方法,一个public的成员变量
编译成功后我们可以用命令:
- javap -s -private JNITest2
看到JNITest2类中的签名。
编写C/C++代码
下面的代码可以当做C/C++代码调用Java代码的事例,主要做了这四件事情:
- 创建虚拟机JVM,在程序结束时销毁虚拟机JVM
- 寻找class对象
- 创建class对象的实例
- 调用方法和修改属性
注意:
-
JNI的函数都是有一定规律的,static就表示静态,没有表示非静态。
-
静态方法是只需要class对象, 不需要实例的, 而非静态方法需要使用我们之前实例化的对象.
jstring
Java的String使用的是Unicode是双字节的字符,而C/C++使用的是单字节的字符。
从C转换为Java字符使用 NewStringUTF方法;从java转换为C的字符,使用GetStringUTFChars
编译运行
编译需要头文件, 头文件在这两个目录中%JAVA_HOME%\include和%JAVA_HOME%\include\win32, 第一个是与平台无关的, 第二个是与平台有关的, 当前系统是windows, 所以是win32.
编译的时候还要一个lib文件, 是对虚拟机的支持, 保证编译通过.
cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 Sample2.c %JAVA_HOME%\lib\jvm.lib
我们可以看到在当前目录下Sample2.exe, 运行的时候需要jvm.dll(不要将其复制到当前目录下, 这样不可以运行, 会导致jvm创建失败)
set PATH=%JAVA_HOME%\jre\bin\client\;%PATH%
Sample2
jvm.dll在%JAVA_HOME%\jre\bin\client\目录下, 所以我把这个目录加入到PATH中, 然后就可以运行