日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Android2.3中Webkit引擎導(dǎo)致VM崩潰的問題

 勤奮不止 2013-04-25

Android2.2,2.3,2.3.3都存在的一個bug,在這里有詳細(xì)的描述。

http://code.google.com/p/android/issues/detail?id=12987

其中,樓主的代碼可以下來運(yùn)行一下,我在2.2和2.3模擬器和2.3的真機(jī)上都存在這個問題。

問題的核心在于這樣一句話:JNI WARNING: jarray 0x4074f6e0 points to non-array object (Ljava/lang/String;)

也就是進(jìn)行JNI調(diào)用時,把一個Java中的String對象當(dāng)數(shù)組來訪問了,最終導(dǎo)致虛擬機(jī)崩潰。

 

先是看到這里(http://code.google.com/p/android/issues/detail?id=12987)有人提到,Google的Nexus S因?yàn)槭褂昧薞8引擎所以不存在這個問題,就把我們系統(tǒng)中的JS引擎由JSC改為V8(具體過程參考這里http://blog.csdn.net/a345017062/archive/2011/04/20/6336753.aspx),發(fā)現(xiàn)問題依然存在。沒辦法只能一步一步地跟蹤了。

 

 

 

對這個問題進(jìn)行跟蹤時,費(fèi)了很大的勁,所以先記錄一下跟蹤過程。

一開始,想著系統(tǒng)有自己的JNI調(diào)用跟蹤系統(tǒng),就使用系統(tǒng)的吧(具體過程這里有http://blog.csdn.net/a345017062/archive/2011/04/28/6369535.aspx),等我把編譯好的.so庫升級到板子上,查看LOG直接傻眼了,沒用的東西太多了,只能自己打印LOG了。

 

 

一共使用了兩個方法,一個是根據(jù)下面這段VM崩潰時系統(tǒng)打印的LOG中提到的拋出異常的本地方法,找出最終調(diào)用哪個函數(shù)時出現(xiàn)了問題。一開始沿著這個思路走,走得很艱難。因?yàn)镴avaScriptCore中某些代碼無法使用LOGW等一系列方法,最后參考了一篇文章(這里有詳細(xì)的描述http://blog.csdn.net/a345017062/archive/2011/05/04/6394897.aspx)才讓LOG出來

 

 

12-20 19:29:34.582: WARN/dalvikvm(725): JNI WARNING: jarray 0x4074f6e0 points to non-array object (Ljava/lang/String;)

12-20 19:29:34.622: INFO/dalvikvm(725): "WebViewCoreThread" prio=5 tid=9 NATIVE

12-20 19:29:34.622: INFO/dalvikvm(725):   | group="main" sCount=0 dsCount=0 obj=0x40521328 self=0x26bea8

12-20 19:29:34.622: INFO/dalvikvm(725):   | sysTid=734 nice=0 sched=0/0 cgrp=default handle=2539488

12-20 19:29:34.632: INFO/dalvikvm(725):   | schedstat=( 5341953614 5808331660 581 )

12-20 19:29:34.632: INFO/dalvikvm(725):   at android.webkit.WebViewCore.nativeTouchUp(Native Method)

12-20 19:29:34.632: INFO/dalvikvm(725):   at android.webkit.WebViewCore.nativeTouchUp(Native Method)

12-20 19:29:34.642: INFO/dalvikvm(725):   at android.webkit.WebViewCore.access$3300(WebViewCore.java:53)

12-20 19:29:34.652: INFO/dalvikvm(725):   at android.webkit.WebViewCore$EventHub$1.handleMessage(WebViewCore.java:1158)

12-20 19:29:34.652: INFO/dalvikvm(725):   at android.os.Handler.dispatchMessage(Handler.java:99)

12-20 19:29:34.652: INFO/dalvikvm(725):   at android.os.Looper.loop(Looper.java:123)

12-20 19:29:34.652: INFO/dalvikvm(725):   at android.webkit.WebViewCore$WebCoreThread.run(WebViewCore.java:629)

12-20 19:29:34.662: INFO/dalvikvm(725):   at java.lang.Thread.run(Thread.java:1019)

12-20 19:29:34.672: ERROR/dalvikvm(725): VM aborting

 

 

另外一個方法就是利用addr2line工具,并結(jié)合下面這段LOG中給出的堆棧信息找到具體出問題的方法。具體過程參考這篇文章

http://blog./space.php?uid=20564848&do=blog&id=94732

 

12-20 19:29:34.852: INFO/DEBUG(30): Build fingerprint: 'generic/sdk/generic:2.3/GRH55/79397:eng/test-keys'

12-20 19:29:34.862: INFO/DEBUG(30): pid: 725, tid: 734  >>> XXXXXXXX <<<

12-20 19:29:34.862: INFO/DEBUG(30): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadd00d

12-20 19:29:34.872: INFO/DEBUG(30):  r0 fffffebc  r1 deadd00d  r2 00000026  r3 00000000

12-20 19:29:34.872: INFO/DEBUG(30):  r4 81da45c8  r5 4074f6e0  r6 81d8592c  r7 0026d2b8

12-20 19:29:34.872: INFO/DEBUG(30):  r8 44174b54  r9 43d72e4c  10 43d72e34  fp 41edd82c

12-20 19:29:34.891: INFO/DEBUG(30):  ip 81da4728  sp 44174348  lr afd19375  pc 81d45a02  cpsr 20000030

12-20 19:29:35.912: INFO/DEBUG(30):          #00  pc 00045a02  /system/lib/libdvm.so

12-20 19:29:35.912: INFO/DEBUG(30):          #01  pc 000376fc  /system/lib/libdvm.so

12-20 19:29:35.912: INFO/DEBUG(30):          #02  pc 000399c4  /system/lib/libdvm.so

12-20 19:29:35.922: INFO/DEBUG(30):          #03  pc 0003a4a0  /system/lib/libdvm.so

12-20 19:29:35.932: INFO/DEBUG(30):          #04  pc 0032b6d6  /system/lib/libwebcore.so

12-20 19:29:35.952: INFO/DEBUG(30):          #05  pc 002a4da4  /system/lib/libwebcore.so

12-20 19:29:35.952: INFO/DEBUG(30):          #06  pc 001a6136  /system/lib/libwebcore.so

12-20 19:29:35.952: INFO/DEBUG(30):          #07  pc 002a5870  /system/lib/libwebcore.so

12-20 19:29:35.962: INFO/DEBUG(30):          #08  pc 00359e36  /system/lib/libwebcore.so

12-20 19:29:35.972: INFO/DEBUG(30):          #09  pc 0035d18e  /system/lib/libwebcore.so

12-20 19:29:35.972: INFO/DEBUG(30):          #10  pc 0036b078  /system/lib/libwebcore.so

12-20 19:29:35.982: INFO/DEBUG(30):          #11  pc 003627ac  /system/lib/libwebcore.so

12-20 19:29:35.982: INFO/DEBUG(30):          #12  pc 0029fb24  /system/lib/libwebcore.so

12-20 19:29:36.002: INFO/DEBUG(30):          #13  pc 0023367e  /system/lib/libwebcore.so

12-20 19:29:36.002: INFO/DEBUG(30):          #14  pc 00239c0c  /system/lib/libwebcore.so

12-20 19:29:36.011: INFO/DEBUG(30):          #15  pc 00237a28  /system/lib/libwebcore.so

12-20 19:29:36.011: INFO/DEBUG(30):          #16  pc 00237b32  /system/lib/libwebcore.so

12-20 19:29:36.022: INFO/DEBUG(30):          #17  pc 0023adba  /system/lib/libwebcore.so

12-20 19:29:36.022: INFO/DEBUG(30):          #18  pc 0023af4e  /system/lib/libwebcore.so

12-20 19:29:36.042: INFO/DEBUG(30):          #19  pc 000f80c0  /system/lib/libwebcore.so

12-20 19:29:36.042: INFO/DEBUG(30):          #20  pc 000f8c66  /system/lib/libwebcore.so

12-20 19:29:36.052: INFO/DEBUG(30):          #21  pc 001b81fa  /system/lib/libwebcore.so

12-20 19:29:36.062: INFO/DEBUG(30):          #22  pc 001b82f2  /system/lib/libwebcore.so

12-20 19:29:36.062: INFO/DEBUG(30):          #23  pc 001b8318  /system/lib/libwebcore.so

12-20 19:29:36.072: INFO/DEBUG(30):          #24  pc 00017d34  /system/lib/libdvm.so

 

 

下面開始分析這個問題

先把這個地址(http://code.google.com/p/android/issues/detail?id=12987)中,樓主的例子下載下來,安裝在機(jī)器上運(yùn)行。發(fā)現(xiàn)問題出在WebView.addJavascriptInterface方法中。只要使用Java擴(kuò)展JS的API,并在腳本中調(diào)用到這些API就會出現(xiàn)VM崩潰。

用上面提到的方法進(jìn)行跟蹤,發(fā)現(xiàn)問題出現(xiàn)在

/external/webkit/WebCore/bridge/jni/jsc/JavaClassJSC.cpp中的這一句上:

if (jarray fields = (jarray)(callJNIMethod<jobject>(aClass, "getFields", "()[Ljava/lang/reflect/Field;"))){

int numFields = env->GetArrayLength(fields);

...

}

callJNIMethod<jobject>方法內(nèi)部出現(xiàn)了錯誤,返回的是一個jstring,在這里把它當(dāng)jarray使用了。在調(diào)用env->GetArrayLength(fields)時,VM會使用/dalvik/vm/CheckJni.c中的checkArray方法對參數(shù)進(jìn)行合法檢驗(yàn),一旦發(fā)現(xiàn)參數(shù)不是數(shù)組,就會調(diào)用abortMaybe()關(guān)閉VM。

 

現(xiàn)在問題到了(jarray)(callJNIMethod<jobject>(aClass, "getFields", "()[Ljava/lang/reflect/Field;"))為什么會返回一個字符串上了。

我在測試用的APK中使用System.out.println(t)對注冊擴(kuò)展API時使用的Test對象進(jìn)行打印,然后把callJNIMethod<jobject>返回的字符串也進(jìn)行打印,發(fā)現(xiàn)兩者相同。也就是說,無論給callJNIMethod<jobject>傳入什么參數(shù),返回結(jié)果都是序列化后的Test對象。

經(jīng)過跟蹤,發(fā)現(xiàn)callJNIMethod最終會調(diào)用/dalvik/vm/interp/Stack.c中的方法dvmCallMethodV,我在dvmCallMethodV中打印了一下method->name,發(fā)現(xiàn)每次callJNIMethod調(diào)用的都是toString方法,這就能解釋為什么callJNIMethod返回的字符串是序列化后的Test對象的現(xiàn)象了。

看來,是callJNIMethod方法把繁瑣的JNI調(diào)用封裝在一起之后出現(xiàn)的問題。于是我自己寫了一個方法來替換callJNIMethod<jobject>:

jobject getReturnObject(JNIEnv* env, jobject anInstance, const char* name,

const char* signature) {

jclass testClass = env->GetObjectClass(anInstance);

if (!testClass) {

LOGW("error 1");

return NULL;

}

jmethodID methodID = env->GetMethodID(testClass, name, signature);

if (!methodID) {

LOGW("error 2");

return NULL;

}

jobject result = env->CallObjectMethod(anInstance, methodID);

if (!result) {

LOGW("error 3");

return NULL;

}

return result;

}

把使用callJNIMethod<jobject>的幾個地方都用getReturnObject方法進(jìn)行替換,問題解決。

 

 

 

參考文章

在Android源碼的JavaScriptCore引擎中添加LOG

http://blog.csdn.net/a345017062/archive/2011/05/04/6394897.aspx

android或linux調(diào)試addr2line工具鎖定命令的使用

http://blog./space.php?uid=20564848&do=blog&id=94732

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多