Adnroid2.3版本模拟器在使用javascript与webkit互动时候报错为bug
最近在做android 的webkit与javascript的测试,发现一个严重的问题,在javascript调用android中的java方法时候,在2.3模拟器下回直接导致vm终止,错误代码如下,但是在2.2下面正常,过后尝试在4.0下的结果,此问题困扰了我2天了,找的好辛苦,特共享出来,以免走弯路:
05-01 00:18:07.523: W/dalvikvm(392): JNI WARNING: jarray 0x40543ad0 points to non-array object (Ljava/lang/String;) 05-01 00:18:07.534: I/dalvikvm(392): "WebViewCoreThread" prio=5 tid=9 NATIVE 05-01 00:18:07.534: I/dalvikvm(392): | group="main" sCount=0 dsCount=0 obj=0x4051e820 self=0x2a5568 05-01 00:18:07.534: I/dalvikvm(392): | sysTid=400 nice=0 sched=0/0 cgrp=default handle=2774688 05-01 00:18:07.534: I/dalvikvm(392): | schedstat=( 1153298463 1944733293 111 ) 05-01 00:18:07.553: I/dalvikvm(392): at android.webkit.LoadListener.nativeFinished(Native Method) 05-01 00:18:07.553: I/dalvikvm(392): at android.webkit.LoadListener.nativeFinished(Native Method) 05-01 00:18:07.563: I/dalvikvm(392): at android.webkit.LoadListener.tearDown(LoadListener.java:1200) 05-01 00:18:07.563: I/dalvikvm(392): at android.webkit.LoadListener.handleEndData(LoadListener.java:721) 05-01 00:18:07.563: I/dalvikvm(392): at android.webkit.LoadListener.handleMessage(LoadListener.java:219) 05-01 00:18:07.573: I/dalvikvm(392): at android.os.Handler.dispatchMessage(Handler.java:99) 05-01 00:18:07.573: I/dalvikvm(392): at android.os.Looper.loop(Looper.java:123) 05-01 00:18:07.573: I/dalvikvm(392): at android.webkit.WebViewCore$WebCoreThread.run(WebViewCore.java:629) 05-01 00:18:07.573: I/dalvikvm(392): at java.lang.Thread.run(Thread.java:1019) 05-01 00:18:07.573: E/dalvikvm(392): VM aborting
google对于此问题的回复:
The javascript to java bridge on 2.3 Gingerbread is causing crashes. This is 100% reproducible using the WebViewDemo application from here: http://code.google.com/p/apps-for-android/source/browse/#svn/trunk/Samples/WebViewDemo. Note: The project file for that app is a little messed up, however, if you recreate the project, keeping the code the same, you can reproduce the error. The sample is old, but the code should still run as none of these interfaces have been deprecated. It is also easily reproducible by creating a simple application that creates a webview, enables javascript, adds a JS interface, then loads a script into the webview. The code for this even simpler app is attached as well as WebViewTest and a secondary Test class as the "bridge". The demos work as expected when using 2.2 This is a serious issue as it will cause crashes for any app using the webview to do any serious work. Thanks in advance for taking a look at this. Attached is the output from logcat as well as the output from adb bugreport.
网上有个牛人对此问题的解决:
下面开始分析这个问题 先把这个地址(http://code.google.com/p/android/issues/detail?id=12987)中,楼主的例子下载下来,安装在机器上运行。发现问题出在WebView.addJavascriptInterface方法中。只要使用Java扩展JS的API,并在脚本中调用到这些API就会出现VM崩溃。 用上面提到的方法进行跟踪,发现问题出现在 /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>方法内部出现了错误,返回的是一个jstring,在这里把它当jarray使用了。在调用env->GetArrayLength(fields)时,VM会使用/dalvik/vm/CheckJni.c中的checkArray方法对参数进行合法检验,一旦发现参数不是数组,就会调用abortMaybe()关闭VM。 现在问题到了(jarray)(callJNIMethod<jobject>(aClass, "getFields", "()[Ljava/lang/reflect/Field;"))为什么会返回一个字符串上了。 我在测试用的APK中使用System.out.println(t)对注册扩展API时使用的Test对象进行打印,然后把callJNIMethod<jobject>返回的字符串也进行打印,发现两者相同。也就是说,无论给callJNIMethod<jobject>传入什么参数,返回结果都是序列化后的Test对象。 经过跟踪,发现callJNIMethod最终会调用/dalvik/vm/interp/Stack.c中的方法dvmCallMethodV,我在dvmCallMethodV中打印了一下method->name,发现每次callJNIMethod调用的都是toString方法,这就能解释为什么callJNIMethod返回的字符串是序列化后的Test对象的现象了。 看来,是callJNIMethod方法把繁琐的JNI调用封装在一起之后出现的问题。于是我自己写了一个方法来替换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方法进行替换,问题解决。
对于牛人的解决方案没有尝试过
相关推荐
nmgxzm00 2020-11-10
ifconfig 2020-10-14
hhanbj 2020-11-17
zfszhangyuan 2020-11-16
古叶峰 2020-11-16
一个智障 2020-11-15
jipengx 2020-11-12
81427005 2020-11-11
xixixi 2020-11-11
游走的豚鼠君 2020-11-10
苗疆三刀的随手记 2020-11-10
Web卓不凡 2020-11-03
小飞侠V 2020-11-02
帕尼尼 2020-10-30
爱读书的旅行者 2020-10-26
帕尼尼 2020-10-23
杏仁技术站 2020-10-23
淼寒儿 2020-10-22