Java通过JNI调用本地C/C++程序
JNI是Java NativeInterface的缩写,中文为JAVA本地调用。使用JNI可以很方便的用我们的Java程序调用C/C++程序。很多时候,某些功能用Java无法实现,比如说涉及到底层驱动的一些功能,这时候我们就可以利用JNI来调用C或者C++程序来实现,这就是JNI的强大之处。但是JNI也有它的缺点,使用java与本地已编译的代码交互,通常会丧失平台可移植性。
下面是一个JNI例子,调用C++输出"helloworld":
第一步:创建Java类,在里面定义一个本地方法(用native关键字修饰的方法)
package com.supre.test;
public class TestNative {
public native void sayHello();
}
第二步:使用javah命令(javah 类的全路径)生成本地方法的C++头文件
在DOS窗口中进入工程中TestNative.class所在目录(如果没有class文件需要先编译产生class文件),然后执行javahTestNative命令,执行完之后就会在当前目录生成一个后缀名为.h的头文件,如com_supre _test_TestNative.h,这个头文件是根据包名和类名来命名的。内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_supre_test_TestNative */
#ifndef _Included_com_supre_test_TestNative
#define _Included_com_supre_test_TestNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_supre_test_TestNative
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_supre_test_TestNative_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
这里可以通过eclipse配置External Tools,来实现run产生该 .h文件
具体步骤如下
a.点击 External Tools -->Externarl ToolsConfigurations,如图
b.选中Program,右键new ,如图
c.根据具体情况,如图填写相关配置,点击apply-->close
名字 | 值 | 说明 |
Name | javahForJNI | 该Program的名字,自定义 |
Location | ${system_path:javah} | 需要执行的命令及路径 |
Working Directory | ${project_loc} | 工作目录 |
Arguments | -v -classpath "${project_loc}/bin/classes" -d "${project_loc}/jni" ${java_type_name} | 执行的参数,这里classpath为类(.class)的路径,${project_loc}表示工程根目录 |
d.添加收藏, External Tools-->organize favorites,如图
e.选中工程中需要生成头文件(.h)的类,Run javahForJNI,如图,可以在上述"${project_loc}/jni"目录下找到头文件。
注意:
1如果报错‘找不到类文件’,则检测路径是否指向classes以及该classes下是否有该类的.class文件
eclipse生成jni对应的.h 文件,参考:http://blog.csdn.net/songyuc/article/details/51347914
第三步:编写C/C++本地代码,生成动态链接库文件
首先在VC6.0(当然也可以用其他工具)中创建一个dll工程---Win32 Dynamic-Link Library工程。然后将上面生成的头文件com_supre_test_TestNative.h添加到该工程中,然后创建一个源文件引用该头文件并且实现头文件中本地函数的功能:
#include<iostream.h>
#include"com_test_TestNative.h"
JNIEXPORT void JNICALL Java_com_test_TestNative_sayHello(JNIEnv *env, jobject obj)
{
cout<<"hello world!"<<endl;
}
这里因为com_test_TestNative.h中引入了jni.h所以要将jni.h加入到VC6.0安装目录下的Include目录中。jni.h在JDK安装目录下的include中,同时得件include/win32中的两个头文件jawt_md.h、jni_md.h也导入到VC6.0中。
第四步:Java调用本地函数
将上述C/C++工程中产生的.dll(或者.so,根据java运行的操作选择windows用.dll,linux用.so)拷贝到java工程lib目录下,然后使用如下调用
package com.supre.test;
public class Test {
public static void main(String[] args) {
System.load(System.getProperty("user.dir")+"/lib/Test.dll");
TestNative t = new TestNative();
t.sayHello();
}
}
TestNative类为第一步中第一的TestNative类