JNI函数接口大全

本文整理了JNI函数接口的常用用法。由参考资料[1]中第13章"JNI Functions",我们可以将jni functions大致分为如下四大类:

1 由VM直接导出的调用接口函数

2 JavaVM接口

3 Native库中定义的函数

4 JNIEnv接口

 以下是代码,涵盖了以下接口用法:

JNI函数接口大全工程实例.zip-Android代码类资源-CSDN下载

github:

https://github.com/hanyuhang-hz/jni-functions

/**
     * Table of methods associated with a single class.
     */
    static JNINativeMethod g_NativeMethods[] = {
		/*      name,                	                signature,               			            funcPtr   */
		{ "native_startTicks", 				    "()V", 							    (void*) Native_StartTicks },
        { "native_stopTicks", 				    "()V", 								(void*) Native_StopTicks },
        { "native_stringOperations", 		    "()V", 								(void*) Native_StringOperations },
        { "native_arrayOperations", 		    "()V", 								(void*) Native_ArrayOperations },
        { "native_objectOperations", 		    "()V", 								(void*) Native_ObjectOperations },
        { "native_classAndInterfaceOperations",   "()V", 								(void*) Native_ClassAndInterfaceOperations },
        { "native_exceptions",                    "()V", 								(void*) Native_Exceptions },
        { "native_globalAndLocalReferences",      "()V", 								(void*) Native_GlobalAndLocalReferences },
        { "native_instanceField",                 "()V", 								(void*) Native_InstanceField },
        { "native_staticField",                   "()V", 								(void*) Native_StaticField },
        { "native_instanceMethod",                "()V", 								(void*) Native_InstanceMethod },
        { "native_staticMethod",                  "()V", 								(void*) Native_StaticMethod },
        { "native_javaVMInterface",               "()V", 								(void*) native_JavaVMInterface },
        { "native_monitorOperations",             "()V", 								(void*) native_monitorOperations },
    };

1 由VM直接导出的调用接口函数

注意:这三个接口只是由VM为JNI导出的三个符号,一般不用用户调用!

1 JNI_GetDefaultJavaVMInitArgs

jint JNI_GetDefaultJavaVMInitArgs(void*);

返回Java虚拟机实现的默认配置。

2 JNI_CreateJavaVM

jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);

加载并初始化一个虚拟机实例。

3 JNI_GetCreatedJavaVMs

jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);

2 JavaVM接口

1 DestroyJavaVM

jint DestroyJavaVM()

卸载JavaVM并释放它的资源。

2 AttachCurrentThread

jint AttachCurrentThread(JNIEnv** p_env, void* thr_args)

绑定当前线程(一般是子线程)到一个虚拟机实例。

3 DetachCurrentThread

jint DetachCurrentThread()

使得当前线程脱离一个虚拟机实例。

4 GetEnv

jint GetEnv(void** env, jint version)

(1)用来检查当前线程是否绑定到给定的虚拟机实例,env设置为NULL,返回错误JNI_EDETACHED.

(2)用来获取其他接口,如JNIEnv的interfaces.

代码:

void *UpdateTicks(void *context) {
    FUNCTION_ENTER;

    TickContext *pctx = (TickContext *) context;
    JavaVM *javaVM = pctx->javaVM;
    JNIEnv *env;
    //(1)因为UpdateTicks属于子线程,子线程并没有绑定到javaVM,所以res返回一定是error
    jint ret = javaVM->GetEnv((void **)&env, JNI_VERSION_1_6);
    LOGD_HYH;
    if (JNI_OK != ret) {
        LOGD_HYH;
        //(2)绑定子线程到虚拟机实例,即初始化env
        ret = javaVM->AttachCurrentThread(&env, NULL);
        if (JNI_OK != ret) {
            LOGE("AttachCurrentThread error,ret = %d", ret);
            return NULL;
        }
    }
    struct timeval beginTime, curTime, usedTime, leftTime;
    const struct timeval kOneSecond = {
            (__kernel_time_t) 1,
            (__kernel_suseconds_t) 0
    };
    jmethodID timerId = env->GetMethodID(pctx->jniManagerClz, "updateTimer", "()V");
    while (1) {
        gettimeofday(&beginTime, NULL);

        pthread_mutex_lock(&pctx->lock);
        int done = pctx->done;
        if (pctx->done) {
            pctx->done = 0;
        }
        pthread_mutex_unlock(&pctx->lock);
        if (done) {
            break;
        }

        env->CallVoidMethod(pctx->jniManagerObj, timerId);

        gettimeofday(&curTime, NULL);
        timersub(&curTime, &beginTime, &usedTime);
        timersub(&kOneSecond, &usedTime, &leftTime);
        struct timespec sleepTime;
        sleepTime.tv_sec = leftTime.tv_sec;
        sleepTime.tv_nsec = leftTime.tv_usec * 1000;

        if (sleepTime.tv_sec <= 1) {
            nanosleep(&sleepTime, NULL);
        } else {
            LOGE("Process too long!");
            break;
        }
    }
    //(3)使得子线程脱离虚拟机实例
    javaVM->DetachCurrentThread();

    FUNCTION_QUIT;
    return context;
}

3 Native库中定义的函数

1 JNI_OnLoad

JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);

当虚拟机加载一个native库时,调用JNI_OnLoad接口。即System.loadLibrary会调用JNI_OnLoad接口。获取JavaVM对象。

2 JNI_OnUnload

JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved);

当虚拟机卸载一个native库时,调用JNI_OnUnload接口。

代码:

/*
 * Returns the JNI version on success, -1 on failure.
 */
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
    FUNCTION_ENTER;

	JNIEnv* env = NULL;
	jint ret;

    g_tickctx.javaVM = vm;
    g_tickctx.done = 0;
    //todo:g_tickctx.javaVM和g_monitorctx.javaVM 同一个即可
    g_monitorctx.javaVM = vm;

	if (JNI_OK != vm->GetEnv((void **) &env, JNI_VERSION_1_6))
	{
        LOGE("GetEnv error!!!");
		return JNI_ERR;
	}
    ret = env->GetVersion();
    LOGD("GetVersion:%x",ret);
	if (Register_Hellolibs_Functions(env) != 0)
	{
		LOGE("Register_Hellolibs_Functions error!!!");
		return JNI_ERR;
	}
    //20190102:test crash debug methods
    //WillCrash();
	/* success -- return valid version number */
	ret = JNI_VERSION_1_6;

    FUNCTION_QUIT;
	return ret;
}

JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved)
{
    FUNCTION_ENTER;

    JNIEnv *env = NULL;
    if (JNI_OK != vm->GetEnv((void **) &env, JNI_VERSION_1_6)) {
        return;
    }

	if (NULL != env)
	{
		Unregisternatives(env);
	}

    FUNCTION_QUIT;
}

4 JNIEnv接口

1 Version Information

1 GetVersion

jint GetVersion()

返回JNIEnv interface的版本号

2 Class and Interface Operations

1 DefineClass 

jclass DefineClass(const char *name, jobject loader, const jbyte* buf, jsize bufLen)

从一个jbyte* buffer里定义一个类

2 FindClass

jclass FindClass(const char* name)

返回一个类的引用

3 GetSuperclass

jclass GetSuperclass(jclass clazz)

返回基类,除了java.lang.Object类(因为java.lang.Object是最基类)

代码:

JNIEXPORT void JNICALL Native_ClassAndInterfaceOperations(JNIEnv *env,jobject obj){
    FUNCTION_ENTER;

    //(1)DefineClass

    //(2)FindClass
    jclass clazz = env->FindClass(HELLOLIBS_JNI_CLASS_NAME);
    jboolean bool_x = env->IsInstanceOf(obj,clazz);
    LOGD("bool_x:%d",bool_x);
    //(3)GetSuperclass
    jclass clazz_super = env->GetSuperclass(clazz);
    jboolean bool_y = env->IsInstanceOf(obj,clazz_super);
    LOGD("bool_y:%d",bool_y);
    env->DeleteLocalRef(clazz);
    env->DeleteLocalRef(clazz_super);

    FUNCTION_QUIT;
}

3 Exceptions

1 FatalError

void FatalError(const char* msg)

打印信息并终止当前虚拟机实例

2 ExceptionCheck

jboolean ExceptionCheck()

检查当前线程是否发生了异常,若有异常返回JNI_TRUE,否则返回JNI_FALSE

3 ExceptionDescribe

void ExceptionDescribe()

JNI层打印异常的堆栈信息!!!

4 ExceptionClear

void ExceptionClear()

清除异常堆栈信息

5 Throw and ThrowNew

jint Throw(jthrowable obj)

丢弃一个现有的异常对象,在当前线程触发一个新的异常

jint ThrowNew(jclass clazz, const char* message)

在当前线程触发一个异常,并自定义输出异常信息

6 ExceptionOccurred

jthrowable ExceptionOccurred()

检查当前线程是否发生了异常,若有异常返回该异常的引用,否则返回NULL

代码:

JNIEXPORT void JNICALL Native_Exceptions(JNIEnv *env,jobject obj){
    FUNCTION_ENTER;

    //(1)FatalError
//    env->FatalError("FatalError!!!");             //will crash


    jclass jCls = env->GetObjectClass(obj);
    jmethodID jMid = env->GetStaticMethodID(jCls,"ExcepitonCallback","()V");        //C层获取Java层静态方法ExcepitonCallback
    if(NULL != jMid){
        env->CallStaticVoidMethod(jCls,jMid);
    }
    LOGD("JNI:ExcepitonCallback");
    //(2)ExceptionCheck
    if(env->ExceptionCheck()){
        LOGE("print exception stack information!!!");
        //(3)ExceptionDescribe
        env->ExceptionDescribe();
        //(4)ExceptionClear
        env->ExceptionClear();
        //(5)ThrowNew
        JNI_ThrowNew(env,"java/lang/Exception","JNI throw exception1!!!");
        //注意:退出前释放相关资源!
        //return ;
    }

    jMid = env->GetStaticMethodID(jCls,"NormalCallback","()V");
    if(NULL != jMid){
        env->CallStaticVoidMethod(jCls,jMid);
    }
    LOGD("JNI:NormalCallback");
    //(6)ExceptionOccurred
    jthrowable jExc = env->ExceptionOccurred();
    if(jExc){
        env->ExceptionDescribe();
        env->ExceptionClear();
        JNI_ThrowNew(env,"java/lang/Exception","JNI throw exception2!!!");
        //注意:退出前释放相关资源!
        //return ;
    }
    env->DeleteLocalRef(jCls);
    env->DeleteLocalRef(jExc);

    FUNCTION_QUIT;
}

4 Global and Local References

1 NewGlobalRef,DeleteGlobalRef

jobject NewGlobalRef(jobject obj)

void DeleteGlobalRef(jobject globalRef)

(1)创建:

调用NewGlobalRef,基于全局引用,弱全局引用,局部引用创建

(2)会阻止GC回收所引用的对象:

只有手动释放全局引用后,垃圾回收机制才可以回收

(3)能跨函数使用,能跨线程使用:

(4)释放:

(i)自动释放:无自动释放

(ii)手动释放:(*env)->DeleteGlobalRef(env,g_cls_string)

2 NewWeakGlobalRef,DeleteWeakGlobalRef

jweak NewWeakGlobalRef(jobject obj)

void DeleteWeakGlobalRef(jweak obj)

(1)创建:

调用NewWeakGlobalRef,基于局部引用或全局引用创建

(2)不会阻止GC回收所引用的对象:

GC认为应该回收它的时候(比如内存紧张的时候)会进行自动回收,从而释放全局弱引用

(3)能跨函数使用,能跨线程使用:

(4)释放:

(i)自动释放:在GC认为应该回收它的时候(比如内存紧张的时候)会进行自动回收,释放全局弱引用

(ii)手动释放:(*env)->DeleteWeakGlobalRef(env,g_cls_string)

3 NewLocalRef,DeleteLocalRef

jobject NewLocalRef(jobject ref)

void DeleteLocalRef(jobject localRef)

(1)创建

调用NewLocalRef或其他JNI接口(FindClass、NewObject、NewCharArray)创建。

(2)会阻止GC回收所引用的对象

只有释放局部引用后GC才可以回收

(3)不能跨函数使用,不能跨线程使用

(4)释放

(i)自动释放:函数返回后局部引用的当前对象会被GC自动释放,所以局部引用是有内存溢出的风险的!例如:在函数体内有循环,循环里New局部引用会出现内存溢出!!!

JNIEXPORT void JNICALL f(JNIEnv *env,jobject obj){

    for(int i=0;i<len;i++){

        jobject strLocalref = env->NewLocalRef(strObject);

        ...

        //如果没有手动释放strLocalref ,只有最后一个strLocalref 会被GC自动释放,其余strLocalref会出现native内存泄漏

        //env->DeleteLocalRef(strLocalref );

    }

}

(ii)手动释放:(*env)->DeleteLocalRef(env,local_ref)

代码:

static jclass g_strCls1;
static jclass g_strCls2;
JNIEXPORT void JNICALL Native_GlobalAndLocalReferences(JNIEnv *env,jobject obj){
    FUNCTION_ENTER;

    //(1)全局引用
    jclass strCls = env->FindClass("java/lang/String");
    g_strCls1 = static_cast<jclass >(env->NewGlobalRef(strCls));

    //(2)全局弱引用
    g_strCls2 = static_cast<jclass >(env->NewWeakGlobalRef(strCls));

    //(3)局部引用
    jmethodID mid = env->GetMethodID(strCls,"<init>","([C)V");
    jstring strUnicode = env->NewStringUTF("hanyuhang");    //(i)create jstring
    const jchar *charUnicode = env->GetStringChars(strUnicode, nullptr);    //(ii)jstring-->jchar*
    jint len = env->GetStringUTFLength(strUnicode);
    LOGD("GetStringUTFLength:%d",len);
    jint len1 = env->GetStringLength(strUnicode);
    LOGD("GetStringLength:%d",len1);

    jcharArray charArr = env->NewCharArray(len);
    env->SetCharArrayRegion(charArr,0,len,charUnicode);                //(iii)jchar*-->jcharArray
    jobject strObject = env->NewObject(strCls,mid,charArr);                 //(iv)jcharArray-->jobject(通过String构造函数)
    jobject strLocalref = env->NewLocalRef(strObject);                      //(v)NewLocalRef
    const char *charUtf = env->GetStringUTFChars(static_cast<jstring >(strLocalref),nullptr);     //(vi)jobject-->char*
    LOGD("charUtf:%s",charUtf);

    
    //GetStringUTFChars/ReleaseStringUTFChars
    env->ReleaseStringUTFChars(static_cast<jstring>(strLocalref),charUtf);
    //(1)删除全局引用
    env->DeleteGlobalRef(g_strCls1);
    //(2)删除全局弱引用
    env->DeleteWeakGlobalRef(g_strCls2);
    //(3)删除局部引用
    env->DeleteLocalRef(strCls);
    env->DeleteLocalRef(strUnicode);
    env->DeleteLocalRef(charArr);
    env->DeleteLocalRef(strObject);
    env->DeleteLocalRef(strLocalref);

    FUNCTION_QUIT;
}

Object Operations

1 GetObjectClass

jclass GetObjectClass(jobject obj)

返回一个对象对应的类

2 IsInstanceOf

jboolean IsInstanceOf(jobject obj, jclass clazz)

检查一个对象是否是一个类的实例

3 NewObject

jobject NewObject(jclass clazz, jmethodID methodID, ...)

分配对象空间并构造该对象

4 AllocObject

jobject AllocObject(jclass clazz)

分配一个未初始化的对象

代码:

JNIEXPORT void JNICALL Native_ObjectOperations(JNIEnv *env,jobject obj){
    FUNCTION_ENTER;

    //(1)GetObjectClass
    jclass clz = env->GetObjectClass(obj);

    //(2)IsInstanceOf
    jboolean bool_x = env->IsInstanceOf(obj,clz);
    LOGD("bool_x:%d",bool_x);
    jclass stringCls = env->FindClass("java/lang/String");
    if(NULL == stringCls){
        LOGE("NULL == stringCls");
        return ;
    }
    jmethodID methodId = env->GetMethodID(stringCls,"<init>","([C)V");
    jstring strUnicode= env->NewStringUTF("testhellolibs!");            //(i)create jstring
    jboolean isCopy = false;
    const jchar *chars = env->GetStringChars(strUnicode,&isCopy);      //(ii)jstring-->jchar*
    int len = env->GetStringLength(strUnicode);
    jcharArray charArray = env->NewCharArray(len);                      //(iii)create jcharArray
    env->SetCharArrayRegion(charArray,0,len,chars);                     //(iv)jchar*-->jcharArray

    //(3)NewObject
    jstring strUnicode1 = (jstring)env->NewObject(stringCls,methodId,charArray);    //jcharArray-->jstring
    const char *charUTF = env->GetStringUTFChars(strUnicode1,&isCopy);             //jstring-->char*
    LOGD("charUTF:%s",charUTF);

    env->DeleteLocalRef(clz);
    env->DeleteLocalRef(stringCls);
    env->DeleteLocalRef(charArray);
    env->DeleteLocalRef(strUnicode);
    env->DeleteLocalRef(strUnicode1);

    FUNCTION_QUIT;
}

Instance Field Access

1 GetFieldID

jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)

获取类的成员域ID

2 Get<Type>Field,Set<Type>Field

jint GetIntField(jobject obj, jfieldID fieldID)

根据成员域ID获取类成员

void SetIntField(jobject obj, jfieldID fieldID, jint value)

根据成员域ID设置类成员

代码:

JNIEXPORT void JNICALL Native_InstanceField(JNIEnv *env,jobject obj){
    FUNCTION_ENTER;

    //Jni局部变量命名习惯:j开头!!!
    jclass jCls = env->GetObjectClass(obj);
    jfieldID jWidthFid = env->GetFieldID(jCls,"mWidth","I");
    int width = env->GetIntField(obj,jWidthFid);
    LOGD("get width:%d",width);
    env->SetIntField(obj,jWidthFid,8);
    width = env->GetIntField(obj,jWidthFid);
    LOGD("set width:%d",width);
    //todo:GetObjectFiled

    FUNCTION_QUIT;
}

7 Static Field Access

1 GetStaticFieldID

jfieldID GetStaticFieldID(jclass clazz, const char* name, const char* sig)

获取类的静态成员域ID

2 GetStatic<Type>Field,SetStatic<Type>Field

jint GetStaticIntField(jclass clazz, jfieldID fieldID)

根据成员域ID获取类静态成员

void SetStaticIntField(jclass clazz, jfieldID fieldID, jint value)

根据成员域ID设置类静态成员

代码:

void Native_StaticField(JNIEnv *env,jobject obj){
    FUNCTION_ENTER;

    jclass jCls = env->FindClass(HELLOLIBS_JNI_CLASS_NAME);
    if(jCls == nullptr){
        return ;
    }
    jfieldID jWidthFid = env->GetStaticFieldID(jCls,"mStaicWidth","I");
    if(jWidthFid == nullptr){
        return ;
    }
    jint jWidth = env->GetStaticIntField(jCls,jWidthFid);
    LOGD("get jNum:%d",jWidth);
    env->SetStaticIntField(jCls,jWidthFid,88);
    jWidth = env->GetStaticIntField(jCls,jWidthFid);
    LOGD("set jNum:%d",jWidth);
    env->DeleteLocalRef(jCls);

    FUNCTION_QUIT;
}

Instance Method Calls

1 GetMethodID

jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)

获取一个类方法的方法ID

2 Call<Type>Method

jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...)

调用类方法

代码:

JNIEXPORT void JNICALL Native_InstanceMethod(JNIEnv *env,jobject obj){
    FUNCTION_ENTER;

    jclass jCls = env->GetObjectClass(obj);
    jmethodID jmid = env->GetMethodID(jCls,"InstanceMethodCallback","()V");
    env->CallVoidMethod(obj,jmid);

    FUNCTION_QUIT;
}

Static Method Calls

1 GetStaticMethodID

jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig)

获取一个类静态方法的方法ID

2 CallStatic<Type>Method

jint (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...);

调用类静态方法

代码:

void Native_StaticMethod(JNIEnv *env,jobject obj){
    FUNCTION_ENTER;

    jclass jCls = env->FindClass(HELLOLIBS_JNI_CLASS_NAME);
    if(jCls == nullptr){
        return ;
    }
    jmethodID static_mid = env->GetStaticMethodID(jCls,"StaticMethodCallback","()V");
    if(static_mid == nullptr){
        return ;
    }
    env->CallStaticVoidMethod(jCls,static_mid);
    env->DeleteLocalRef(jCls);           //删除jCls局部引用

    FUNCTION_QUIT;
}

10 String Operations

char*(1字节)~UTF-8字符串

jchar*(2字节)~Unicode字符串

1 NewString

jstring NewString(const jchar* unicodeChars, jsize len)

通过jchar*创建一个jstring对象

2 NewStringUTF

jstring NewStringUTF(const char* bytes)

通过char*创建一个jstring对象

3 GetStringLength

jsize GetStringLength(jstring string)

返回jstring的长度

4 GetStringUTFLength

jsize GetStringUTFLength(jstring string)

返回jstring的长度

5 GetStringChars/ReleaseStringChars

const jchar* GetStringChars(jstring string, jboolean* isCopy)

通过jstring获取jchar*指针

void ReleaseStringChars(jstring string, const jchar* chars)

释放jstring对应的jchar*指针

6 GetStringUTFChars/ReleaseStringUTFChars

const char* GetStringUTFChars(jstring string, jboolean* isCopy)

通过jstring获取char*指针

void ReleaseStringUTFChars(jstring string, const char* utf)

释放jstring对应的char*指针

7 GetStringCritical/ReleaseStringCritical

const jchar* GetStringCritical(jstring string, jboolean* isCopy)

通过jstring获取jchar*指针

void ReleaseStringCritical(jstring string, const jchar* carray)

释放jstring对应的jchar*指针

8 GetStringRegion/GetStringUTFRegion

void GetStringRegion(jstring str, jsize start, jsize len, jchar* buf)

将jstring对象拷贝到jchar*内存

void GetStringUTFRegion(jstring str, jsize start, jsize len, char* buf)

将jstring对象拷贝到char*内存

代码:

JNIEXPORT void JNICALL Native_StringOperations(JNIEnv *env,jobject obj){
    FUNCTION_ENTER;

    //(1)Unicode String Operations
    jstring str = env->NewStringUTF("testhellolibs1");
    jint len = env->GetStringUTFLength(str);
    LOGD("len:%d",len);
    const jchar *strchar = env->GetStringChars(str, nullptr);
    for (jint i = 0; i < len; i++) {
        LOGD("strchar:%c", strchar[i]);
    }
    //GetStringChars/ReleaseStringChars
    env->ReleaseStringChars(str,strchar);
    //虽然函数结束后,LocalRef str会自动释放,还是要养成手动释放的习惯
    env->DeleteLocalRef(str);


    //(2)UTF String Operations
    jstring strutf = env->NewStringUTF("testhellolibs2");
    jint lenutf = env->GetStringUTFLength(strutf);
    LOGD("lenutf:%d",lenutf);
    const char *strcharutf = env->GetStringUTFChars(strutf, nullptr);
    for (int i = 0; i < lenutf; i++) {
        LOGD("strcharutf:%c", strcharutf[i]);
    }
    //GetStringUTFChars/ReleaseStringUTFChars
    env->ReleaseStringUTFChars(strutf,strcharutf);
    env->DeleteLocalRef(strutf);


    //(3)GetStringCritical
    jstring strcritical = env->NewStringUTF("testhellolibs3");
    jint lencritical = env->GetStringUTFLength(strcritical);
    LOGD("lencritical:%d",lencritical);
    const jchar* jcharscritical = env->GetStringCritical(strcritical,NULL);
    for(int i = 0;i < lencritical;i++){
        LOGD("jcharscritical:%c", jcharscritical[i]);
    }
    //GetStringCritical/ReleaseStringCritical
    env->ReleaseStringCritical(strcritical,jcharscritical);
    env->DeleteLocalRef(strcritical);

    //(4)GetStringUTFRegion
    jstring strregion = env->NewStringUTF("testhellolibs4");
    jint lenregion = env->GetStringUTFLength(strregion);
    LOGD("lenregion:%d",lenregion);
    char buff1[128];
    char* pBuff1 = buff1;
    env->GetStringUTFRegion(strregion,0,lenregion,pBuff1);
    for(int i=0;i < lenregion;i++){
        LOGD("buff1:%c",buff1[i]);
    }
    env->DeleteLocalRef(strregion);

    FUNCTION_QUIT;
}

11 Array Operations

1 GetArrayLength

jsize GetArrayLength(jarray array)

返回数组元素个数

2 NewObjectArray

jobjectArray NewObjectArray(jsize length, jclass elementClass,jobject initialElement)

创建对象数组

3 New<Type>Array

jintArray NewIntArray(jsize length)

创建基本类型数组(int,char...)

4 GetObjectArrayElement/SetObjectArrayElement

jobject GetObjectArrayElement(jobjectArray array, jsize index)

获取对象数组元素

void SetObjectArrayElement(jobjectArray array, jsize index, jobject value)

设置对象数组元素

5 Get<Type>ArrayElements/Release<Type>ArrayElements

jint* GetIntArrayElements(jintArray array, jboolean* isCopy)

获取基本类型数组内存指针

void ReleaseIntArrayElements(jintArray array, jint* elems,jint mode)

释放基本类型数组内存

6 Get<Type>ArrayRegion/Set<Type>ArrayRegion

void GetIntArrayRegion(jintArray array, jsize start, jsize len,jint* buf)

拷贝jintArray到jint*

void SetIntArrayRegion(jintArray array, jsize start, jsize len,const jint* buf)

拷贝const jint*到jintArray

代码:

JNIEXPORT void JNICALL Native_ArrayOperations(JNIEnv *env, jobject obj) {
    FUNCTION_ENTER;

    //(1)基本类型
    //(i)NewIntArray
    int len = 3;
    jintArray intArray = env->NewIntArray(len);
    if (NULL == intArray) {
        LOGD("NULL == ret");
        return ;
    }
    //(ii)GetArrayLength
    jint arrayLen = env->GetArrayLength(intArray);
    LOGD("arrayLen:%d", arrayLen);
    //(iii)GetIntArrayRegion/SetIntArrayRegion
    int tmp[3]={7,8,9};
    env->SetIntArrayRegion(intArray,0,arrayLen,tmp);
    int array[3];
    env->GetIntArrayRegion(intArray,0,arrayLen,array);
    for(int i=0;i<arrayLen;i++){
        LOGD("tmp1:%d ",array[i]);
    }
    //(iv)GetIntArrayElements/ReleaseIntArrayElements
    jboolean isCopy;
    jint *c_array = env->GetIntArrayElements(intArray,&isCopy);
    LOGD("isCopy:%d ",isCopy);
    if(c_array == nullptr){
        LOGE("GetIntArrayElements error!!!");
        return ;
    }
    for(int i = 0;i<arrayLen;i++){
        LOGD("get:%d ",c_array[i]);
    }
    env->ReleaseIntArrayElements(intArray,c_array,0);
    env->DeleteLocalRef(intArray);


    //(2)Object类型
    int lenObject = 5;
    jclass stringArrCls = env->FindClass("java/lang/String");
    if (NULL == stringArrCls) {
        LOGD("NULL == stringArrCls");
        return ;
    }
    //(i)NewObjectArray
    jobjectArray objectArray = env->NewObjectArray(lenObject, stringArrCls, 0);      //0:jobject initialElement
    if (NULL == objectArray) {
        LOGD("NULL == objectArray");
        return ;
    }
    //(ii)GetArrayLength
    jint arrayLenObject = env->GetArrayLength(objectArray);
    LOGD("arrayLenObject:%d", arrayLenObject);
    //(iii)GetObjectArrayElement/SetObjectArrayElement
    char *sa[]={"Hello","Han","yu","hang","!!!"};
    for(int i=0;i<arrayLenObject;i++){
        jstring str = env->NewStringUTF(sa[i]);
        env->SetObjectArrayElement(objectArray,i,str);
        env->DeleteLocalRef(str);
    }
    for(int i=0;i<arrayLenObject;i++){
        jstring str = (jstring)env->GetObjectArrayElement(objectArray,i);
        jboolean isCopy;
        const char *chars = env->GetStringUTFChars(str, &isCopy);
        LOGD("isCopy:%d,chars:%s",isCopy,chars);
        env->ReleaseStringUTFChars(str,chars);
    }
    env->DeleteLocalRef(objectArray);

    FUNCTION_QUIT;
}

12 Native Method Registration

1 RegisterNatives/UnregisterNatives

jint RegisterNatives(jclass clazz, const JNINativeMethod* methods,jint nMethods)

注册native方法

jint UnregisterNatives(jclass clazz)

注销native方法

代码:

jint Register_Hellolibs_Functions(JNIEnv * env)
{
    FUNCTION_ENTER;

	jclass clazz = env->FindClass(HELLOLIBS_JNI_CLASS_NAME);
	if (clazz == 0)
	{
		return -1;
	}

    /**
     * Table of methods associated with a single class.
     */
    static JNINativeMethod g_NativeMethods[] = {
		/*      name,                	                signature,               			            funcPtr   */
		{ "native_startTicks", 				    "()V", 							    (void*) Native_StartTicks },
        { "native_stopTicks", 				    "()V", 								(void*) Native_StopTicks },
        { "native_stringOperations", 		    "()V", 								(void*) Native_StringOperations },
        { "native_arrayOperations", 		        "()V", 								(void*) Native_ArrayOperations },
        { "native_objectOperations", 		    "()V", 								(void*) Native_ObjectOperations },
        { "native_classAndInterfaceOperations",   "()V", 								(void*) Native_ClassAndInterfaceOperations },
        { "native_exceptions",                    "()V", 								(void*) Native_Exceptions },
        { "native_globalAndLocalReferences",      "()V", 								(void*) Native_GlobalAndLocalReferences },
        { "native_instanceField",                 "()V", 								(void*) Native_InstanceField },
        { "native_staticField",                   "()V", 								(void*) Native_StaticField },
        { "native_instanceMethod",                "()V", 								(void*) Native_InstanceMethod },
        { "native_staticMethod",                  "()V", 								(void*) Native_StaticMethod },
        { "native_javaVMInterface",               "()V", 								(void*) native_JavaVMInterface },
        { "native_monitorOperations",             "()V", 								(void*) native_monitorOperations },
    };

	jint nMethods = sizeof(g_NativeMethods) / sizeof(JNINativeMethod);
	jint res = env->RegisterNatives(clazz, g_NativeMethods, nMethods);
	if (res < 0)
	{
		return -1;
	}
	env->DeleteLocalRef(clazz);

    FUNCTION_QUIT;
	return 0;
}

static void UnregisterNativeMethods(JNIEnv* env, const char* className)
{
    FUNCTION_ENTER;

	jclass clazz;
	clazz = env->FindClass(className);
	if (NULL == clazz)  return;

	if (NULL != env)
	{
		env->UnregisterNatives(clazz);
	}

    FUNCTION_QUIT;
}

13 Monitor Operations

1  MonitorEnter

jint MonitorEnter(jobject obj)

进入临界区

2  MonitorExit

jint MonitorExit(jobject obj)

退出临界区

代码:

void native_monitorOperations(JNIEnv *env,jobject obj){
    FUNCTION_ENTER;

    //(1)创建线程monitorThread2
    pthread_t threadInfo_;
    pthread_attr_t threadAttr_;
    pthread_attr_init(&threadAttr_);
    pthread_attr_setdetachstate(&threadAttr_, PTHREAD_CREATE_DETACHED);

    jclass clz = env->GetObjectClass(obj);
    g_monitorctx.jniManagerClz = static_cast<jclass>(env->NewGlobalRef(clz));            //static_cast<jclass>:jobject-->jclass
    g_monitorctx.jniManagerObj = env->NewGlobalRef(obj);

    int res = pthread_create(&threadInfo_, &threadAttr_,monitorThread2, &g_monitorctx);
    assert(res == 0);

    //(2)MonitorEnter/MonitorExit
    if(env->MonitorEnter(obj)!=JNI_OK){
        LOGE("MonitorEnter error!!!");
        return ;
    }
    //进入临界区
    for(int i=0;i<20;i++){
        globle_monitor++;
        LOGD("globle_monitor:%d thread:%lu",globle_monitor,pthread_self());
    }
    if(env->MonitorExit(obj)!=JNI_OK){
        LOGE("MonitorExit error!!!");
        return ;
    }
    //(3)pthread_attr_destroy
    pthread_attr_destroy(&threadAttr_);

    FUNCTION_QUIT;
}

14 JavaVM Interface

1  GetJavaVM

jint GetJavaVM(JavaVM** vm)

获取当前虚拟机JavaVM指针

代码:

void native_JavaVMInterface(JNIEnv *env,jobject obj){
    FUNCTION_ENTER;

    static JavaVM *pJavaVM = nullptr;
    env->GetJavaVM(&pJavaVM);
    LOGD("pJavaVM:%p",pJavaVM);

    FUNCTION_QUIT;
}

5 参考资料

[1]The Java™ Native Interface Programmer’s Guide and Specification.pdf

[2]JNI/NDK开发指南

https://blog.csdn.net/xyang81/article/category/2759987

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值