java的jni模块可以实现本地方法的调用,当java语言无法实现某个功能,或者效率比较低下,可以调用效率较高的c或者c++,这里以c举例。
运行环境:
jdk1.8 32位
visual studio 2013
idea
主要包括三步:
- 使用java编写函数声明,方法上标明native,使用javah命令生成头文件。
- 使用c语言实现声明的函数,同时导入jni.h,jni_md.h,和上述生成的头文件。
- 编写java代码,加载动态链接库,调用c。
详细过程如下:
- java语言编写函数声明,标明native。
package com.company.jni;
public class NativeTest {
public static native void greeting();
}
在源文件所在目录下,执行
javac -h . NativeTest.java
生成字节码文件和头文件
如图:
也可以在src目录下,执行以下命令也可以生成头文件javah com.company.jni.NativeTest
如图:
使用visual studio创建动态链接库,注意不要使用codeblocks,这个会报错,创建过程如图:
选择DLL、空项目。
接着在项目的根目录下,添加三个头文件,直接复制即可。
- com_company_jni_NativeTest.h 第一步生成的头文件
- jni.h 在jdk/include目录下
- jni_md.h 在jdk/include/win32目录下
接着需要在解决方案资源管理器中的头文件添加现有项,添加这三个头文件。
接着在源文件添加新建项,创建test.c源文件,需要实现
com_company_jni_NativeTest.h中的函数声明。注意这个函数的名称是有讲究的。同时将这个文件的#include<jni.h> 改为#include “jni.h”。
JNIEXPORT void JNICALL Java_com_company_jni_NativeTest_greeting
(JNIEnv *, jclass);
test.c文件
#include<stdio.h>
#include "com_company_jni_NativeTest.h"
JNIEXPORT void JNICALL Java_com_company_jni_NativeTest_greeting(JNIEnv * env, jclass cl){
printf("hello world!");
}
- 编写java代码,NativeTestDemo.java
package com.company.jni;
public class NativeTestDemo {
static{
System.loadLibrary("native");
// 不用加后缀名称
}
public static void main(String[] args) {
NativeTest.greeting();
}
}
注意,动态链接库在目录native/Debug下,不需要后缀名,需要在idea运行时,做如下配置,指定动态链接库的目录。
具体步骤:点击edit configurations,在vm添加如下命令行参数。
-Djava.library.path=E:\Projects\native\Debug
同时需要注意如果使用codeblocks生成的动态链接库报错如下:
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.company.jni.NativeTest.greeting()V
使用jdk1.8 64位,报错如下:
E:\Projects\native\Debug\native.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
所以使用visual studio和jdk1.8 32位。
运行结果如图,调用成功。