最近在做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方法进行替换,问题解决。
对于牛人的解决方案没有尝试过
相关推荐
如果我们编写了一个Android应用程序,想在一台没有Android SDK或者BUILD环境的机器显示给别人看,应该怎么办呢? 打开压缩文件,运行里面的run.bat文件,这时候就会启动android模拟器
在装这个之前,我只能刷的小米2.3.7的系统,用的是那个网上下的2.3版本可用的java模拟器,就是把jbed.apk文件复制到system/app里面,libjbedvm.so文件复制到system/lib里面并改权限的那个。这个直装版出来以后,...
如果我们编写了一个Android应用程序,想在一台没有Android SDK或者BUILD环境的机器显示给别人看,应该怎么办呢?...本资源是一个压缩包,解压之后双击运行里面的run.bat批处理文件即可启动android 2.3模拟器
标题中的“android2.3可用的java模拟器”指的是在Android 2.3(Gingerbread)操作系统上能够运行的Java应用程序模拟器。这通常涉及到Java虚拟机(JVM)的实现,因为Java应用程序需要在这样的环境中才能被执行。在...
在安卓系统上,尤其是针对较旧版本如安卓2.3(也称为Gingerbread),Java模拟器提供了在非Android设备或者不支持特定API级别的设备上运行Java应用的能力。这里我们主要讨论的是一个针对安卓2.3系统的Java模拟器,...
Android 2.3 SDK,又称为Gingerbread(姜饼),是Google针对其移动操作系统Android发布的一个重要版本。这个SDK(软件开发工具包)为开发者提供了构建、测试和调试针对Android 2.3系统应用所需的工具和技术文档。...
《Android2.3应用开发实战源代码》是林城撰写的一本书,主要针对的是Android 2.3(Gingerbread)版本的应用程序开发。这本书通过实际案例的方式,深入浅出地介绍了如何在Android 2.3平台上构建和优化应用程序。在源...
安卓系统2.3可装的JAVA模拟器直安装版-新版,1、下载安装R.E.管理器rootexplorer(有的ROM已集成就不用了) 2、用R.E.管理器rootexplorer将下载的libjbmidp.so,libjbmidpdy.so,libjbedvm.so文件放入system\lib目录...
本文将详细介绍如何在不同操作系统上安装Android 2.3 SDK,并创建和运行Android虚拟设备(AVD)。 首先,你需要从官方渠道下载适用于你操作系统的Android 2.3 SDK。Windows用户可以下载`android-sdk_r08-windows....
这个阶段的Android系统版本,也称为Gingerbread,是Android平台的一个重要里程碑,为开发者提供了更多的特性和优化,旨在提升用户体验和开发效率。本实战指南由林城撰写,他是一位经验丰富的Android开发者,分享了他...
在进入Android应用开发的世界之前,首先需要正确地搭建Android SDK 2.3和Eclipse的开发环境。这个过程虽然看似繁琐,但遵循正确的步骤,你可以轻松完成。以下是一份详细的搭建指南,旨在帮助你顺利开始Android编程之...
在此,我们可以得到模拟器的 DNS 地址,默认为“10.0.2.3”,默认 IP 地址为“10.0.2.15”。 四、设置模拟器的 DNS 在 adb shell 命令行中,输入 setprop net.dns1 192.168.5.1 命令,即可把 DNS 修改成电脑 DNS。 ...
在Android开发过程中,Android模拟器扮演着至关重要的角色,它为开发者提供了一个可以在桌面系统上运行和测试Android应用的环境。然而,由于模拟器的网络配置与开发者的主机系统不一致,这可能导致通信问题,例如...
eoeAndroid特刊第十四期:Android2.3特色讲解 pdf,目录:姜饼Android2.3的新特性介绍、有关NFC技术,Android2.3的模拟器Emulator安装教程,以及一些android2.3的翻译资料和实例教程等。
在本文中,我们将深入探讨如何在Ubuntu 32位系统上安装、编译Android 2.3源码以及内核,并解决编译过程中可能遇到的问题。Android 2.3,也被称为Gingerbread,是Android操作系统的一个重要版本,对开发者来说具有...
标题中的“全屏2.3_java模拟器”指的是一个针对Android系统的Java模拟器,它能够让你在Android设备上运行基于Java 2.3(也称为Gingerbread)平台的应用程序。这种模拟器允许用户在全屏模式下体验原本只适用于Java...
在进行Android应用开发的过程中,开发者经常需要使用Android模拟器来进行应用程序的测试与调试。然而,在某些情况下,模拟器可能会遇到无法联网的问题,这不仅影响了应用的功能测试,还可能对整个开发流程造成阻碍。...
在使用Android模拟器的过程中,有些用户可能会遇到模拟器无法识别或使用键盘输入的情况。这种情况可能是由于模拟器设置不当、驱动程序冲突或系统兼容性问题导致的。对于经常依赖键盘进行快速测试和调试的开发者来说...