天天看点

Java JNI简单实现

<b>Java JNI简单实现</b>

         JNI(Java Native Interface)允许了Java和C&amp;C++进行交互?这不折腾人嘛!

<b>一、JNI简述</b>

<b>二、JNI基本类型</b>

         copy表一份,很详细的了!

<b>Java</b><b>类型</b>

<b>本地类型</b>

<b>描述</b>

boolean

jboolean

C/C++8位整型

byte

jbyte

C/C++带符号的8位整型

char

jchar

C/C++无符号的16位整型

short

jshort

C/C++带符号的16位整型

int

jint

C/C++带符号的32位整型

long

jlong

C/C++带符号的64位整型

float

jfloat

C/C++32位浮点型

double

jdouble

C/C++64位浮点型

Object

jobject

任何Java对象,或者没有对应java类型的对象

Class

jclass

Class对象

String

jstring

字符串对象

Object[]

jobjectArray

任何对象的数组

boolean[]

jbooleanArray

布尔型数组

byte[]

jbyteArray

比特型数组

char[]

jcharArray

字符型数组

short[]

jshortArray

短整型数组

int[]

jintArray

整型数组

long[]

jlongArray

长整型数组

float[]

jfloatArray

浮点型数组

double[]

jdoubleArray

双浮点型数组

表2 Java类型映射

<b>三、Java调用C&amp;C++</b>

         1)Java类中编写native声明的方法。

         2)javah命令生成JNI样式.h文件。

         貌似我一直是直接建一个.h,然后copy之前的改改完事。需要注意以下几点:1、JNI调用函数必须要用C编译器编译。也就是C++别忘了extern "C"那块;2、方法名格式:Java_pacakege_class_method。

例子程序的HelloJni.h文件:

#ifndef HELLOJNI_H_ 

#define HELLOJNI_H_ 

#include &lt;jni.h&gt; 

// JNI调用函数必须要用C编译器编译 

// C++不加extern "C",调用会有异常 

#ifdef __cplusplus 

extern "C" { 

#endif 

/* 

 * 1、JNIEXPORT、JNICALL:jni的宏 

 * 2、jstring:返回值类型(对应java的string) 

 * 3、C方法名:Java_pacakege_class_method 

 * 4、JNIEnv*、jobject:jni必要参数(jni环境、java对象) 

 */ 

JNIEXPORT void JNICALL Java_org_join_jni_JniTest_sayHelloWin (JNIEnv*, jobject, int, int, int, int); 

#endif /* HELLOJNI_H_ */ 

         3)用C&amp;C++方法实现本地方法,编译成动态库

         4)Java类中用System.loadLibrary()或System.load()方法加载生成的dll文件

                  System.loadLibrary():装载Windows\System32下或jre\bin或Tomcat\bin目录下的本地链接库

                  System.load():根据具体的目录来加截本地链接库,必须是绝对路径

         5)OK!

         注意jni方法的使用,C&amp;C++格式是不一样的,如下:

                  C 格式:(*env) -&gt; &lt;jni function&gt; (env, &lt;parameters&gt;)

                  返回jstring:return (*env)-&gt;NewStringUTF(env, "XXX");

                  C++ 格式:env -&gt; &lt;jni function&gt; (&lt;parameters&gt;)

                  返回jstring:return env-&gt;NewStringUTF("XXX");

         另外数组类型的话,jni提供了操作的函数,稍复杂点,例子里没写也就不说了。

<b>四、C&amp;C++回调Java</b>

         直接看代码吧,每步都有注释了。

<b>1)包org.join.jni下类JniTest内定义的两方法</b>

/** C回调Java方法(静态) */ 

public static int add(int x, int y) { 

System.out.println("==Java静态add方法=="); 

return x + y; 

/** C回调Java方法(非静态) */ 

public int sub(int x, int y) { 

System.out.println("==Java非静态sub方法=="); 

return x - y; 

<b>2)CallJava.h</b>

#ifndef CALLJAVA_H_ 

#define CALLJAVA_H_ 

#include &lt;stdio.h&gt; 

#include &lt;stdlib.h&gt; 

int add(JNIEnv*, int, int); 

int sub(JNIEnv*, int, int); 

jobject getInstance(JNIEnv*, jclass); 

#endif /* CALLJAVA_H_ */ 

<b>3)CallJava.cpp</b>

#include "CallJava.h" 

/** 

 * C回调Java方法(静态) 

int add(JNIEnv *env, int x, int y) { 

    // 获取类 

    jclass AnalyzeCidUtil = env-&gt;FindClass("org/join/jni/JniTest"); 

    if (NULL == AnalyzeCidUtil) { 

        return -1; 

    } 

    // 获取类add静态方法 

    /* 

     * 第三个参数为方法签名 

     * 

     * 可用JDK自带工具javap生成该类所有方法签名 

     * 控制台进入该类class文件目录,输入:javap -s -private 类名 

     */ 

    jmethodID add = env-&gt;GetStaticMethodID(AnalyzeCidUtil, "add", "(II)I"); 

    if (NULL == sub) { 

        env-&gt;DeleteLocalRef(AnalyzeCidUtil); // 删除类指引 

        return -2; 

    // 调用静态int方法 

    int result = env-&gt;CallStaticIntMethod(AnalyzeCidUtil, add, x, y); 

    // 返回结果 

    return result; 

 * C回调Java方法(非静态) 

int sub(JNIEnv *env, int x, int y) { 

    // 实例化类对象 

    jobject mAnalyzeCidUtil = getInstance(env, AnalyzeCidUtil); 

    if (NULL == mAnalyzeCidUtil) { 

    // 获取对象sub方法 

    jmethodID sub = env-&gt;GetMethodID(AnalyzeCidUtil, "sub", "(II)I"); 

        env-&gt;DeleteLocalRef(mAnalyzeCidUtil); // 删除类对象指引 

        return -3; 

    // 调用非静态int方法 

    int result = env-&gt;CallIntMethod(mAnalyzeCidUtil, sub, x, y); 

 * 实例化类对象 

jobject getInstance(JNIEnv *env, jclass clazz) { 

    // 获取构造方法 

    jmethodID constructor = env-&gt;GetMethodID(clazz, "&lt;init&gt;", "()V"); 

    if (NULL == constructor) { 

        return NULL; 

    return env-&gt;NewObject(clazz, constructor); 

         注意静态和非静态方法相差的实例化类对象的区别!

<b>五、后记</b>

         附件样例工程有两个,JavaJni是Java工程,JniDll_win32是VS2010工程。

         Java工程带了在我环境下编译的dll,可直接跑,但我相信大多数人都跑不通-_-!(在朋友电脑上曾试过,可能是Java不同版本的原因吧)

         总之不行或者非win32系统的话重新编译吧,源文件在JniDll_win32工程内都有。注意include Java安装目录下include文件夹内的头文件哦。VS2010的话,右键工程 -&gt; Properties -&gt; Configuration Properties -&gt; C/C++ -&gt; General -&gt; Additional Include Directories内设置,如:%JAVA_HOME%\include;%JAVA_HOME%\include\win32。

<a href="http://down.51cto.com/data/2359729" target="_blank">附件:http://down.51cto.com/data/2359729</a>

     本文转自winorlose2000 51CTO博客,原文链接:http://blog.51cto.com/vaero/770139,如需转载请自行联系原作者