博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java_jni编程全面解析
阅读量:2434 次
发布时间:2019-05-10

本文共 7739 字,大约阅读时间需要 25 分钟。

JNI简介

JNI 是 Java Native Interface 的缩写。 Java 本机接口(Java Native Interface,JNI)是一个标准的 Java API,它支持将 Java 代码与使用其他编程语言编写的代码相集成。如果您希望利用已有的代码资源,那么可以使用 JNI 作为您工具包中的关键组件。

下面介绍通过java程序调用C语言编写函数的库函数
宿主机:Ubuntu12.04
java_jdk:openjdk-1.7.0
c编译器:GCC_4.5

1.无参数无返回值的调用

JNI.java

public class JNI {
static { //1.load加载C库 System.loadLibrary("native");//libnative.so // } public native static void hello("native"); public static void main(String[] args) { //2.java.hello()-c.hello() //C库函数与java函数的映射 //3.call,调用C库 JNI.hello(); }}

编译 #javac JNI.java

生成头文件#javah -jni JNI
jv_v.c

#include
#include
typedef struct { char *name; /* Java里调用的函数名 */ char *signature; /* JNI字段描述符, 用来表示Java里调用的函数的参数和返回值类型 */ void *fnPtr; /* C语言实现的本地函数 */} JNINativeMethod;static const JNINativeMethod methods[] = { {
"hello", "()V", (void *)c_hello},//此处分别为java函数名,JNI字段描述符(可参考下方的表 //格),C中的函数指针};javac JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *jvm, void *reserved){ JNIEnv *env; jclass cls; if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) { return JNI_ERR; /* JNI version not supported */ } cls = (*env)->FindClass(env, "JNI"); if (cls == NULL) { return JNI_ERR; } if((*env)->RegisterNatives(env,cls,methods,1)<0) return JNI_ERR; return JNI_VERSION_1_4;}void c_hello(JNIEnv *env,jobject cls){ printf("hello world\n");}

#gcc -I/usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -fPIC -shared -o libnative.so jv_v.c

然后将生成的libnative.so库文件放到java文件目录下,使用java命令执行即可

JNI数据类型及JNI字段描述符

这里写图片描述

有参数有返回值(传入int变量,返回int变量)

JNI2.java

public class JNI2 {    static {        System.loadLibrary("native");    }    public native static int hello(int m);    public static void main(String[] args) {        System.out.print(JNI2.hello(120));    }}

编译 #javac JNI2.java

生成头文件#javah -jni JNI2
jint_int.c

#include
#include
#if 0typedef struct{ char *name;//java char *signature;//JNI void *fnPtr;//}JNINativeMethod;#endif // 0jint JNICALL Java_JNI3_hello (JNIEnv *env, jclass cls, jint m);static const JNINativeMethod methods[] = { {
"hello", "(I)I", (void *)c_hello},};JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *jvm, void *reserved){ JNIEnv *env; jclass cls; if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) { return JNI_ERR; /* JNI version not supported */ } cls = (*env)->FindClass(env, "JNI2"); if (cls == NULL) { return JNI_ERR; } if((*env)->RegisterNatives(env,cls,methods,1)<0) return JNI_ERR; return JNI_VERSION_1_4;}jint c_hello(JNIEnv *env,jobject cls,jint m){ printf("hello world,val = %d\n",m); return 100;}

#gcc -I/usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -fPIC -shared -o libnative.so jint_int.c

然后将生成的libnative.so库文件放到java文件目录下,使用java命令执行即可

传入字符串返回字符串

public class JNI3 {    static {        System.loadLibrary("native");    }    public native static String hello(String str);    public static void main(String[] args) {        System.out.print(JNI2.hello("chen"));    }}

编译 #javac JNI3.java

生成头文件#javah -jni JNI3
js_s.c

#include
#include
#if 0typedef struct{ char *name;//java char *signature;//JNI void *fnPtr;//}JNINativeMethod;#endif //jstring c_hello(JNIEnv *env, jclass cls, jstring str);static const JNINativeMethod methods[] = { {
"hello", "(Ljava/lang/String;)Ljava/lang/String;", (void *)c_hello},//此处描述符的 //不同};JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *jvm, void *reserved){ JNIEnv *env; jclass cls; if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) { return JNI_ERR; /* JNI version not supported */ } cls = (*env)->FindClass(env, "JNI2"); if (cls == NULL) { return JNI_ERR; } if((*env)->RegisterNatives(env,cls,methods,1)<0) return JNI_ERR; return JNI_VERSION_1_4;}jstring c_hello(JNIEnv * env, jclass cls, jstring str) { /*此处需要字符串做转化处理,负责不能直接输出和返回 */ const jbyte *cstr; cstr = (*env)->GetStringUTFChars(env,str,NULL);//将字符串重新转化 if(cstr==NULL) { return NULL; } printf("hello world,c is %s\n",cstr); (*env)->ReleaseStringUTFChars(env,str,cstr);//将字符串重新转化返回 return (*env)->NewStringUTF(env,"from c");}

#gcc -I/usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -fPIC -shared -o libnative.so js_s.c

然后将生成的libnative.so库文件放到java文件目录下,使用java命令执行即可

传入数组返回int类型

JNI4.java

public class JNI4{    static {        System.loadLibrary("native");    }    public native static int hello(int[] a);    public static void main(String[] args) {        int[] a = {
1,2,3}; System.out.print(JNI4.hello(a)); }}编译 #javac JNI4.java 生成头文件#javah -jni JNI4

ja_i.c

#include
#include
#if 0typedef struct{ char *name;//java char *signature;//JNI void *fnPtr;//}JNINativeMethod;#endif // 0jint c_hello(JNIEnv *env, jclass cls, jintArray arr);static const JNINativeMethod methods[] = { {
"hello", "([I)I", (void *)c_hello},};JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *jvm, void *reserved){ JNIEnv *env; jclass cls; if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) { return JNI_ERR; /* JNI version not supported */ } cls = (*env)->FindClass(env, "JNI4"); if (cls == NULL) { return JNI_ERR; } if((*env)->RegisterNatives(env,cls,methods,1)<0) return JNI_ERR; return JNI_VERSION_1_4;}jint c_hello(JNIEnv *env, jclass cls, jintArray arr){ jint *carr; jint i,sum = 0; carr = (*env)->GetIntArrayElements(env,arr,NULL); if(carr==NULL) return 0; for(i=0;i<(*env)->GetArrayLength(env,arr);i++) { sum = sum+carr[i]; } (*env)->ReleaseIntArrayElements(env,arr,carr,0); return sum;}

#gcc -I/usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -fPIC -shared -o libnative.so ja_i.c

然后将生成的libnative.so库文件放到java文件目录下,使用java命令执行即可

传入数组参数返回数组

public class JNI5 {
static { System.loadLibrary("native"); } public native static int[] hello(int[] a); public static void main(String[] args) { int[] a = {
1,2,3}; int[] b = null; b = JNI5.hello(a); for(int i =0;i

编译 #javac JNI5.java

生成头文件#javah -jni JNI5
ja_a.c

#include
#include
#include
#if 0typedef struct{ char *name;//java char *signature;//JNI void *fnPtr;//}JNINativeMethod;#endif // 0jintArray c_hello(JNIEnv *env, jclass cls, jintArray arr);static const JNINativeMethod methods[] = { {
"hello", "([I)[I", (void *)c_hello},};JNIEXPORT jint JNICALLJNI_OnLoad(JavaVM *jvm, void *reserved){ JNIEnv *env; jclass cls; if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) { return JNI_ERR; /* JNI version not supported */ } cls = (*env)->FindClass(env, "JNI5"); if (cls == NULL) { return JNI_ERR; } if((*env)->RegisterNatives(env,cls,methods,1)<0) return JNI_ERR; return JNI_VERSION_1_4;}jintArray c_hello(JNIEnv *env, jclass cls, jintArray arr){ jint *carr; jint *oarr; jintArray rarr; jint i,n = 0; carr = (*env)->GetIntArrayElements(env,arr,NULL);//数组转化 if(carr==NULL) return 0;//转化失败 n =(*env)->GetArrayLength(env,arr);//获取传入数组长度 oarr = malloc(sizeof(jint)*n);//分配内存空间 if(oarr==NULL) { (*env)->ReleaseIntArrayElements(env,arr,carr,0);//释放 return 0; } for(i=0;i
ReleaseIntArrayElements(env,arr,carr,0); rarr = (*env)->NewIntArray(env,n); if(rarr==NULL) { return 0; } (*env)->SetIntArrayRegion(env,rarr,0,n,oarr); free(oarr);//释放内存空间 return rarr;}

#gcc -I/usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -fPIC -shared -o libnative.soja_a.c

然后将生成的libnative.so库文件放到java文件目录下,使用java命令执行即可

你可能感兴趣的文章
【Java】-- Java核心知识点总结
查看>>
【数据库】突破单一数据库的性能限制——数据库-分库分表总结 2018-9-20
查看>>
Slurm——作业调度处理
查看>>
Lustre 维护
查看>>
Lustre—磁盘配额测试
查看>>
SSH加密密码中的非对称式密码学
查看>>
Mac Redis安装入门教程
查看>>
python3安装教程配置配置阿里云
查看>>
Mac快捷键和实用技巧
查看>>
Git的多人协作和分支处理测试
查看>>
mysql索引回表
查看>>
iterm2 保存阿里云登陆并防止断开连接
查看>>
brew安装
查看>>
mysql5.7初始密码查看及密码重置
查看>>
go语言实现2048小游戏(完整代码)
查看>>
动态二维码免费制作
查看>>
C语言贪吃蛇
查看>>
Python练手项目
查看>>
知网毕业论文爬取
查看>>
Django无法显示图片
查看>>