这几天一直在摸索java的JNI特性,现在总算是阶段性地厘清了一些技术细节。
学习前请检查java环境配置,能在cmd.exe中输入java -version能显示环境信息,如:
D:\workspace>java -version
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) Client VM (build 23.1-b03, mixed mode, sharing)
说明环境成功配置完成 。
1.什么是JNI
JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。
这段话摘自百度,意思是说,java一般是运行在JAVA虚拟机上,而虚拟机又是运行在真实机上的,为了让java可以绕过虚拟机,直接在真实机上执行二进制代码,java提供了JNI这种机制。但这种机制下编写的代码是和目标实体机平台密切相关的。所以这样的代码不能移植到其他平台上,比如在windows写的JNI程序,不能移植到linux平台,反之亦然。
2.java的代码编写
public class Test{
public native void PrintInfo();//定义了native函数,即此函数将由其他语言编写,此源代码中只是声明即可。
static{
System.loadLibrary("test");//注意此处是static代码块,在java中,static代码块将在类加载时自动执行,System.loadLibrary函数将加载test.dll动态库,注意没有后缀
}
public void Callback()//此处的函数将在native函数中被调用。
{
System.out.println("Here is in java space,and i am function Callback");
}
public static void main(String[] args){
new Test().PrintInfo();//调用native函数时,先实例化类的对象,然后在对象中调用native函数。
}
}
代码如上,将其保存为Test.java,并在cmd窗口中执行编译命令:javac Test.java,得到Test.class文件后,然后执行头文件生成命令:javah Test,即可得到Test.h文件,此头文件将用于c代码的编写。所以可以将其路径包含进vc6的头文件路径中。
3.native的代码编写
#include "stdafx.h"
#include "test.h" //包含javah Test生成头文件,其实是声明了Java_Test_PrintInfo函数
JNIEXPORT void JNICALL Java_Test_PrintInfo(JNIEnv *env , jobject obj)//笔者的头文件中并无env,obj变量,读者自行添加
{
WinExec("calc.exe",1);
jclass cls=env->GetObjectClass(obj);
jmethodID funid = env->GetMethodID(cls,"Callback","()V");
printf("here is native space\n");
env->CallVoidMethod(obj,funid,NULL);//调用java文件中的Callback函数
printf("here is native space\n");
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
编译成test.dll后,将其移到Test.class文件的目录下。
4.最后测试
在cmd中执行java Test,效果如下: