Java通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在Windows平台下是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使Java可以实现和本地机器的紧密联系,调用系统级的各接口方法
1、在Java程序中,首先需要在类中声明所调用的库名称,如
static { System.loadLibrary(“testdll”); }
2、还需要对将要调用的方法做本地声明,关键字为native。且只需要声明,而不需要具体实现
public native static void set(int i); public native static int get();
public class TestJNI { static { System.loadLibrary("testdll"); } public native static int get(); public native static void set(int i); public static void main(String[] args) { testdll test = new testdll(); test.set(10); System.out.println(test.get()); } }3、使用javac TestJNI.java编译它,得到TestJNI.class
再用javah TestJNI,则会在当前目录下生成TestJNI.h文件
注意:用javah命令生成相应h头文件的时候有可能会出现无法找到相应class文件的错误,建议使用如下格式在控制台生成.h头文件
D:\>javah -classpath . testdll
1、打开VC++,新建工程->win32 DLL,在向导中选择空工程。然后编写testdll.cpp文件
#include <windows.h> #include "TestJNI.h" int i = 0; JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass) { return i; } JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j) { i = j; } int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) { return TRUE ; }
说明:
(1)必须有DllMain函数,并且DllMain必须返回TRUE,否则系统将终止程序并弹出一个“启动程序时出错”对话框,其他两个为Java中调用的两个函数的实现,解释见最后的补充
(2)把Java编译生成的TestJNI.h加入到C/C++的工程中,否则上面代码的include "TestJNI.h"无法引用到
2、编译上面的testdll.cpp文件,可以生成testdll.dll文件,但是这过程通常会出现:在TestJNI.h中找不到jni.h
解决方法:把Javajdk中的下面这些.h文件复制一份到Microsoft Visual Studio的安装目录下的\VC\include文件夹下,例如笔者的是D:\Program Files\Microsoft Visual Studio 10.0\VC\include
\jdk\include\jni.h \jdk\include\win32\jawt_md.h \jdk\include\win32\jni_md.h
1、生成的DLL文件的名称要跟Java代码中需要调用的testdll一样,如果不同可以修改文件名,这里是testdll.dll
2、然后把该dll文件拷贝到TestJNI.class文件的目录下。
3、使用java testdll 运行它,就可以观察到结果
说明:如果运行java testdll 出现错误:“ 找不到或无法加载主类”,可能是环境变量的classpath键值的分号;掉了,一般掉了这个就会出现这种问题
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class TestJNI*/ #ifndef _Included_TestJNI #define _Included_TestJNI #ifdef __cplusplus extern "C" { #endif /* * Class: TestJNI * Method: get * Signature: ()I */ JNIEXPORT jint JNICALL Java_TestJNI_get (JNIEnv *, jclass); /* * Class: TestJNI * Method: set * Signature: (I)V */ JNIEXPORT void JNICALL Java_TestJNI_set (JNIEnv *, jclass, jint); #ifdef __cplusplus } #endif #endif在具体实现的时候,我们只关心两个函数原型