java_jni编程全面解析

来源:互联网 发布:淘宝第三层级什么意思 编辑:程序博客网 时间:2024/05/18 04:01

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<stdio.h>#include<jni.h>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<stdio.h>#include<jni.h>#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<stdio.h>#include<jni.h>#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<stdio.h>#include<jni.h>#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<b.length;i++)            System.out.print(b[i]);    }}

编译 #javac JNI5.java
生成头文件#javah -jni JNI5
ja_a.c

#include<stdio.h>#include<jni.h>#include<stdlib.h>#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<n;i++)    {        oarr [i] = carr[n-i-1];//逆序转化    }    (*env)->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命令执行即可

1 0
原创粉丝点击