java jni 博客_Java JNI简单实现

Java JNI简单实现

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

一、JNI简述

二、JNI基本类型

copy表一份,很详细的了!

Java

类型

本地类型

描述

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类型映射

三、Java调用C&C++

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 

// 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 voidJNICALL Java_org_join_jni_JniTest_sayHelloWin (JNIEnv*, jobject,int,int,int,int);

#ifdef __cplusplus

}

#endif

#endif /* HELLOJNI_H_ */

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

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

System.loadLibrary():装载Windows\System32下或

jre\bin或

Tomcat\bin目录下的本地链接库

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

5)OK!

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

C 格式:(*env) -> (env, )

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

C++ 格式:env -> ()

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

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

四、C&C++回调Java

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

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

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

publicstaticintadd(intx,inty) {

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

returnx + y;

}

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

publicintsub(intx,inty) {

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

returnx - y;

}

2)CallJava.h

#ifndef CALLJAVA_H_

#define CALLJAVA_H_

#include 

#include 

#include 

intadd(JNIEnv*,int,int);

intsub(JNIEnv*,int,int);

jobject getInstance(JNIEnv*, jclass);

#endif /* CALLJAVA_H_ */

3)CallJava.cpp

#include "CallJava.h"

/**

* C回调Java方法(静态)

*/

intadd(JNIEnv *env,intx,inty) {

// 获取类

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

if(NULL == AnalyzeCidUtil) {

return-1;

}

// 获取类add静态方法

/*

* 第三个参数为方法签名

*

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

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

*/

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

if(NULL == sub) {

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

return-2;

}

// 调用静态int方法

intresult = env->CallStaticIntMethod(AnalyzeCidUtil, add, x, y);

// 返回结果

returnresult;

}

/**

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

*/

intsub(JNIEnv *env,intx,inty) {

// 获取类

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

if(NULL == AnalyzeCidUtil) {

return-1;

}

// 实例化类对象

jobject mAnalyzeCidUtil = getInstance(env, AnalyzeCidUtil);

if(NULL == mAnalyzeCidUtil) {

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

return-2;

}

// 获取对象sub方法

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

if(NULL == sub) {

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

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

return-3;

}

// 调用非静态int方法

intresult = env->CallIntMethod(mAnalyzeCidUtil, sub, x, y);

// 返回结果

returnresult;

}

/**

* 实例化类对象

*/

jobject getInstance(JNIEnv *env, jclass clazz) {

// 获取构造方法

jmethodID constructor = env->GetMethodID(clazz, "","()V");

if(NULL == constructor) {

returnNULL;

}

// 实例化类对象

returnenv->NewObject(clazz, constructor);

}

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

五、后记

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值