JNI基础语法

本文详细介绍了JNI的基础语法,包括Java和JNI类型对照、JNI函数的解析和区别,以及JNI常用函数如字符串处理、数组操作、访问Java类的方法和字段等。还探讨了JNI中线程同步、异常处理、对象引用的管理,并提供了调用Java构造方法和父类实例方法的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 Java和JNI类型对照

1.1 基本类型对照表

Java类型 Native类型 C/C++类型 大小
Boolean jboolean unsigned char 无符号8位
Byte jbyte char 有符号8位
Char jchar unsigned short 无符号16位
Short jshort short 有符号16位
Integer jint int 有符号32位
Long jlong long long 有符号64位
Float jfloat float 32位浮点值
Double jdouble double 64位双精度浮点值

1.2 引用类型对照表

Java类型 Native类型
java.lang.Class jclass
java.lang.Throwable jthrowable
java.lang.String jstring
java.lang.Object jobject
java.util.Objects jobjects
java.lang.Object[] jobjectArray
Boolean[] jbooleanArray
Byte[] jbyteArray
Char[] jcharArray
Short[] jshortArray
int[] jintArray
long[] jlongArray
float[] jfloatArray
double[] jdoubleArray
通用数组 jarray
说明任何Java数组在JNI里面都可以使用jarray来表示,比如Java的int[]数组,用JNI可以表示为jintArray,也可以表示为jarray

二、JNI函数详解

2.1 JNI函数的解析

首先我们需要在Java代码里面声明Native方法原型,比如:

public native void helloJNI(String msg);

其次我们需要在C/C++代码里面声明JNI方法原型,比如:

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_helloJNI(JNIEnv* env, jobject thiz,jstring msg) {
   
   
    //do something
}

JNI函数的原型
[extern “C”]JNIEXPORT 函数返回值 JNICALL 完整的函数声明(JNIENV *env, jobject thiz, …)

extern "C"根据需要动态添加,如果是C++代码,则必须要添加extern “C”声明,如果是C代码,则不用添加。

JNIEXPORT 这个关键字说明这个函数是一个可导出函数,学过C/C++的朋友都知道,C/C++ 库里面的函数有些可以直接被外部调用,有些不可以,原因就是每一个C/C++库都有一个导出函数列表,只有在这个列表里面的函数才可以被外部直接调用,类似Java的public函数和private函数的区别。

JNICALL 说明这个函数是一个JNI函数,用来和普通的C/C++函数进行区别,实际发现不加这个关键字,Java也是可以调用这个JNI函数的。

Void 说明这个函数的返回值是void,如果需要返回值,则把这个关键字替换成要返回的类型即可。

Java_com_kgdwbb_jnistudy_MainActivity_helloJNI(JNIEnv*env, jobject thiz,jstring msg)这是完整的JNI函数声明,JNI函数名的原型如下:
Java_ + JNI方法所在的完整的类名,把类名里面的”.”替换成”_” + 真实的JNI方法名,这个方法名要和Java代码里面声明的JNI方法名一样+ JNI函数必须的默认参数(JNIEnv* env, jobjectthiz)

  • env参数是一个指向JNIEnv函数表的指针,
  • thiz参数代表的就是声明这个JNI方法的Java类的引用
  • msg参数就是和Java声明的JNI函数的msg参数对于的JNI函数参数

2.2 静态JNI方法和实例JNI方法区别

Java代码:

public native void showHello();
public native static void showHello2();

JNI代码:

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_showHello(JNIEnv* env, jobject thiz) {
   
   
    //do something
}

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_showHello2(JNIEnv* env, jclass thiz) {
   
   
    //do something
}

普通的JNI方法对应的JNI函数的第二个参数是jobject类型,而静态的JNI方法对应的JNI函数的第二个参数是jclass类型

三、JNI常用函数

3.1 JNI字符串相关的函数

C/C++字符串转JNI字符串

NewString函数用来生成Unicode JNI字符串
NewStringUTF函数用来生成UTF-8 JNI字符串

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_testJString(JNIEnv* env, jobject thiz,jstring jstr) {
   
   
    char *str="helloboy";
    jstring jstr2=env->NewStringUTF(str);

    const jchar *jchar2=env->GetStringChars(jstr,NULL);
    size_t len=env->GetStringLength(jstr);
    jstring jstr3=env->NewString(jchar2,len);
}

JNI字符串转C/C++字符串

GetStringChars函数用来从jstring获取Unicode C/C++字符串
GetStringUTFChars函数用来从jstring获取UTF-8 C/C++字符串

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_testJString(JNIEnv* env, jobject thiz,jstring jstr) {
   
   
    const char *str=env->GetStringUTFChars(jstr,NULL);
    const jchar *jchar2=env->GetStringChars(jstr,NULL);
}

释放JNI字符串

ReleaseStringChars函数用来释放Unicode C/C++字符串
ReleaseStringUTFChars函数用来释放UTF-8 C/C++字符串

当你的本地代码使用完通过 GetStringUTFChars 获取的 UTF-8 字符串后,调用 ReleaseStringUTFChars 表明本地代码不再需要 GetStringUTFChars 返回的 UTF-8 字符串了,就能够释放掉 UTF-8 字符串占用的内存。不调用 ReleaseStringUTFChars 进行内存释放会导致内存泄漏,最终导致内存耗尽。

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_testJString(JNIEnv* env, jobject thiz,jstring jstr) {
   
   
    const char *str=env->GetStringUTFChars(jstr,NULL);
    env->ReleaseStringUTFChars(jstr,str);

    const jchar *jchar2=env->GetStringChars(jstr,NULL);
    env->ReleaseStringChars(jstr,jchar2);
}

JNI字符串截取

GetStringRegion函数用来截取Unicode JNI字符串
GetStringUTFRegion函数用来截取UTF-8 JNI字符串

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_testJString(JNIEnv* env, jobject thiz,jstring jstr) {
   
   
    const char *str=env->GetStringUTFChars(jstr,NULL);
    char *subStr=new char;
    env->GetStringUTFRegion(jstr,0,3,subStr);
    env->ReleaseStringUTFChars(jstr,str);

    const jchar *jchar2=env->GetStringChars(jstr,NULL);
    jchar *subJstr=new jchar;
    env->GetStringRegion(jstr,0,3,subJstr);
    env->ReleaseStringChars(jstr,jchar2);
}

获取JNI字符串的长度

GetStringLength用来获取Unicode JNI字符串的长度
GetStringUTFLength函数用来获取UTF-8 JNI字符串的长度

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_testJString(JNIEnv* env, jobject thiz,jstring jstr) {
   
   
    jsize len=env->GetStringLength(jstr);
    jsize len2=env->GetStringUTFLength(jstr);
}

3.2 JNI数组相关的函数

JNI数组相关的类

Java类型 Native类型
java.lang.Object[] jobjectArray
Boolean[] jbooleanArray
Byte[] jbyteArray
Char[] jcharArray
Short[] jshortArray
int[] jintArray
long[] jlongArray
float[] jfloatArray
double[] jdoubleArray
通用数组 jarray
说明任何Java数组在JNI里面都可以使用jarray来表示,比如Java的int[]数组,用JNI可以表示为jintArray,也可以表示为jarray

获取JNI基本类型数组元素

Get< Type>ArrayElements函数用来获取基本类型JNI数组的元素,这里面的< Type>需要被替换成实际的类型,比如GetIntArrayElementsGetLongArrayElements

extern "C"
JNIEXPORT void JNICALL
Java_com_kgdwbb_jnistudy_MainActivity_testJIntArray(JNIEnv* env, jobject thiz,jintArray array) {
   
   
    jint *intArray=env->GetIntArrayElements(array,NULL);
    int len=env->GetArrayLength(array);
    for(int i=0;i<len;i++){
   
   
        jint item=intArray[i];
    }
}
</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值