本文整理了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;
}
5 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;
}
6 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;
}
8 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;
}
9 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开发指南