java_jni编程全面解析

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 JNICALL
JNI_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 0
typedef struct{
    char *name;//java
    char *signature;//JNI
    void *fnPtr;//
}JNINativeMethod;
#endif // 0
jint JNICALL Java_JNI3_hello
  (JNIEnv *env, jclass cls, jint m);
static const JNINativeMethod methods[] = {
    {"hello", "(I)I", (void *)c_hello},
};

JNIEXPORT jint JNICALL
JNI_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 0
typedef 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 JNICALL
JNI_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 0
typedef struct{
    char *name;//java
    char *signature;//JNI
    void *fnPtr;//
}JNINativeMethod;
#endif // 0

jint c_hello(JNIEnv *env, jclass cls, jintArray arr);
static const JNINativeMethod methods[] = {
    {"hello", "([I)I", (void *)c_hello},
};

JNIEXPORT jint JNICALL
JNI_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 0
typedef struct{
    char *name;//java
    char *signature;//JNI
    void *fnPtr;//
}JNINativeMethod;
#endif // 0
jintArray c_hello(JNIEnv *env, jclass cls, jintArray arr);
static const JNINativeMethod methods[] = {
    {"hello", "([I)[I", (void *)c_hello},
};

JNIEXPORT jint JNICALL
JNI_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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值