JNI调用小结
1.简介
JNI的全称是Java Native Interface,翻译过来就是java本地接口,用来实现java与vc++/vb…之间的调用、传值。对它更多了解请参看java文档。
对于java开发人员而言,实现JNI调用简单来说基本有四步:
第一, 按照JNI调用规则写一个java类 (如XebNew.java)
第二, 使用”javac”命令编译该java类,生成class文件(XebNew.class)
第三, 使用”javah”命令生成.h文件(XebNew.h),该文件是在c(或其他)方法中的要引用到的头文件
第四, 运行调用该java类
2.示例一
下面以不带包(package)的java类的JNI调用为例简单说明
1)先写java类
public class XebNew {
static {
System.out.println(“java.library.path:”+ System.getProperty("java.library.path"));
System.loadLibrary("xebdeal");
}
public native String doXebNewId(String filePath, String id);
public static void main(String[] args) {
XebNew hh = new XebNew();
String returnStr = hh.doXebNewId( "xeb", "test");
System.out.println("result = " + returnStr);
}
}
2)编绎工程生成.class文件
3)生成.h文件
启动命令行(开始->运行 cmd.exe),从当前目录转至XebNew.class所在的目录,执行
”javah XebNew”的命令,生成” XebNew.h”的头文件(注意不要写成javah XebNew.class),这正是c++需要的头文件
生成的.h文件如下:
#include <jni.h>
/* Header for class XebNew */
#ifndef _Included_ XebNew
#define _Included_ XebNew
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: XebNew
* Method: doXebNewId
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_ XebNew _ doXebNewId
(JNIEnv *, jobject, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endif
接下来就是c 的部分了,最后要用这个头文件生成一个xebdeal的库文件。如果是在Windows平台下用,则应生成 xebdeal.dll(windows对大小写不敏感);如果是在linux平台,则应生成libxebdeal.so库文件
4)使用”java XebNew”命令运行该类
将xebdeal.dll或者libxebdeal.so加到相应”java.library.path”(此路径通过前面的XebNew类的输出语句中获得)中,使用”java XebNew”命令运行该类。注意,如果库文件存放位置不正确会产生如下错误:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no xebdeal in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1682)
at java.lang.Runtime.loadLibrary0(Runtime.java:822)
at java.lang.System.loadLibrary(System.java:993)
at XebNew.<clinit>(XebNew.java:9)
3.示例二
一般而言,在工程项目中,类是在某个包(package),如下:
package com.founder.mnp.domain;
/**
* 调用c方法的类
* @author chen.lm
*
*/
public class XebNew {
static {
System.out.println("java.library.path: " + System.getProperty("java.library.path"));
logger.info("java.library.path: " + System.getProperty("java.library.path"));
try{
System.loadLibrary("xebdeal");
} catch(UnsatisfiedLinkError e)
{
System.err.println( "Cannot load hello library:/n " +
e.toString() );
}
}
/**
*
* @param filePath 文件路径
* @param id
* @param keys 向文件指定位置插入的char值
* @return
*/
public native int doXebNewId(String filePath, String id, char[]keys);
}
如果用上例所说的过程来完成,则会出现如下错误:
Exception in thread "main" java.lang.UnsatisfiedLinkError: doXebNewId
at com.founder.mnp.domain.XebNew.doXebNewId(Native Method)
at com.founder.mnp.domain.XebNew.main(XebNew.java:48)
注意这个错误与上例错误的区别,原因就在于包。
如果XebNew的类在包com.founder.mnp.domain下面,那么必须到相应的class目录下面执行“javah com.founder.mnp.domain. XebNew”即可得到.h文件,文件名为:com_founder_mnp_domain_XebNew.h。
留意:如果你的class文件在目录E:/workspace/mnp21/WebRoot/WEB-INF/classes/com/founder/mnp/domain下,则黄色部分为你包名,你需要在E:/workspace/mnp21/WebRoot/WEB-INF/classes下运行“javah com.founder.mnp.domain. XebNew”命令。
剩下的就和上例一样了。
4. 小结
看完文档,应该JNI已经入了小门了,呵呵!实际可能有更复杂的情况,如生成的库文件(.dll/.so)依赖其他多个库文件。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/icecreamchen/archive/2009/03/23/4016440.aspx