jni調(diào)試最蛋疼的就是signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4這種錯(cuò)誤百姓,爆出來完全不知道是哪句代碼造成的,很難定位到問題所在耀盗,網(wǎng)上很多人說是內(nèi)存原因荸实,還有說是空指針蔽莱,不一而論内颗。
我的錯(cuò)誤是這樣的:
02-16 14:54:53.041 20897-20897/? I/AEE/AED: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x4
02-16 14:54:53.058 20897-20897/? I/AEE/AED: r0 00000001 r1 00000002 r2 00000000 r3 0000002f
02-16 14:54:53.058 20897-20897/? I/AEE/AED: r4 00000000 r5 f4489000 r6 f4400000 r7 f6fb3c0c
02-16 14:54:53.058 20897-20897/? I/AEE/AED: r8 f48000c0 r9 f6fb3c0c sl 00000001 fp 00000002
02-16 14:54:53.058 20897-20897/? I/AEE/AED: ip f6fb3c24 sp dc144060 lr 00000000 pc f6f7f566 cpsr 600f0030
02-16 14:54:53.059 20897-20897/? I/AEE/AED: backtrace:
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #00 pc 00042566 /system/lib/libc.so (je_arena_dalloc_bin_locked+365)
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #01 pc 0004fa0b /system/lib/libc.so (je_tcache_bin_flush_small+234)
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #02 pc 0004a33f /system/lib/libc.so (ifree+446)
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #03 pc 00035775 /data/app/我的包名-1/lib/arm/libjni-lib.so (std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >::~basic_string()+148)
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #04 pc 00086087 /data/app/我的包名-1/lib/arm/libjni-lib.so (WPZHandler::OnRspQryPosition(TradingLibFast::RspQryPositionResponse*)+2518)
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #05 pc 0004451d /data/app/我的包名-1/lib/arm/libjni-lib.so (TradingLibFast::TLClient::HandleMessage(TradingLibFast::Message&)+964)
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #06 pc 00041083 /data/app/我的包名-1/lib/arm/libjni-lib.so (TradingLibFast::TLClient::RecvFun()+226)
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #07 pc 00066cfb /data/app/我的包名-1/lib/arm/libjni-lib.so (fastdelegate::FastDelegate0<bool>::operator()() const+94)
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #08 pc 00066889 /data/app/我的包名-1/lib/arm/libjni-lib.so (TradingLibFast::TLThread::ProcessInThread()+68)
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #09 pc 00066837 /data/app/我的包名-1/lib/arm/libjni-lib.so (TradingLibFast::ThreadFunc(void*)+26)
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #10 pc 00017003 /system/lib/libc.so (__pthread_start(void*)+30)
02-16 14:54:53.059 20897-20897/? I/AEE/AED: #11 pc 0001506f /system/lib/libc.so (__start_thread+6)
然后就是nativeCrashListener沛鸵,這個(gè)log其實(shí)已經(jīng)很清晰了蛾娶,記得一定不要過濾灯谣,選擇no Filters,日志級別選擇Verbose最低級別蛔琅,這樣才能看到最全的log信息胎许。je_arena_dalloc_bin_locked顯示就是內(nèi)存處理出問題了,jni代碼出問題導(dǎo)致了系統(tǒng)錯(cuò)誤罗售。再往下包含“我的包名”的log信息就顯示了錯(cuò)誤的具體位置辜窑,越上面就是越具體的位置,越下面范圍就越廣寨躁,這里大致就定位了問題代碼大概在哪幾行穆碎。不過這幾行我糾結(jié)了許久,因?yàn)橛X得沒有問題职恳,閃退只是偶現(xiàn)所禀,后來看到另外一篇文章:常見 core dump 原因分析signal 11 - SIGSEGV,說signal 11 (SIGSEGV)是由于內(nèi)存釋放不當(dāng)(多次釋放或者空釋放)或者空指針引起的,遂檢查放钦,終于發(fā)現(xiàn)了問題:
在調(diào)用NewStringUTF方法的時(shí)候使用了ReleaseStringUTFChars進(jìn)行釋放色徘,這個(gè)釋放內(nèi)存的方法并不能在此處使用,應(yīng)該使用DeleteLocalRef來釋放引用即可操禀。
jni具體內(nèi)存釋放對應(yīng)方法如下:
總體原則:釋放所有對object的引用
1.FindClass
例如褂策,
jclass ref= (env)->FindClass("java/lang/String");
env->DeleteLocalRef(ref);
2.NewString/ NewStringUTF/NewObject/NewByteArray
例如,
jstring (*NewString)(JNIEnv*, const jchar*, jsize);
const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*); void (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*);
jstring (*NewStringUTF)(JNIEnv*, const char*);
const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*); void (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*);
env->DeleteLocalRef(ref);
3.GetObjectField/GetObjectClass/GetObjectArrayElement
jclass ref = env->GetObjectClass(robj);
env->DeleteLocalRef(ref);
4.GetByteArrayElements和GetStringUTFChars
jbyte* array= (*env)->GetByteArrayElements(env,jarray,&isCopy);
(*env)->ReleaseByteArrayElements(env,jarray,array,0);
const char* input =(*env)->GetStringUTFChars(env,jinput, &isCopy);
(*env)->ReleaseStringUTFChars(env,jinput,input);
5.NewGlobalRef/DeleteGlobalRef
jobject (NewGlobalRef)(JNIEnv, jobject);
void (DeleteGlobalRef)(JNIEnv, jobject);
例如颓屑,
jobject ref= env->NewGlobalRef(customObj);
env->DeleteGlobalRef(customObj);
改完果然就沒有再閃退了辙培!