在android7.0,一个游戏点击进入的时候,出现了force close,出现问题的log如下,
06-07 01:58:10.910 E/AndroidRuntime(19880): FATAL EXCEPTION: main
06-07 01:58:10.910 E/AndroidRuntime(19880): Process: com.naquatic.monstercrafter, PID: 19880
06-07 01:58:10.910 E/AndroidRuntime(19880): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.naquatic.monstercrafter/com.unity3d.player.UnityPlayerNativeActivity}: java.lang.ClassCastException: g.u.CustomClassLoader cannot be cast to dalvik.system.BaseDexClassLoader
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.app.ActivityThread.-wrap12(ActivityThread.java)
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.os.Handler.dispatchMessage(Handler.java:102)
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.os.Looper.loop(Looper.java:154)
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.app.ActivityThread.main(ActivityThread.java:6077)
06-07 01:58:10.910 E/AndroidRuntime(19880): at java.lang.reflect.Method.invoke(Native Method)
06-07 01:58:10.910 E/AndroidRuntime(19880): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
06-07 01:58:10.910 E/AndroidRuntime(19880): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
06-07 01:58:10.910 E/AndroidRuntime(19880): Caused by: java.lang.ClassCastException: g.u.CustomClassLoader cannot be cast to dalvik.system.BaseDexClassLoader
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.app.NativeActivity.onCreate(NativeActivity.java:164)
06-07 01:58:10.910 E/AndroidRuntime(19880): at com.unity3d.player.UnityPlayerNativeActivity.onCreate(Unknown Source)
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.app.Activity.performCreate(Activity.java:6705)
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
06-07 01:58:10.910 E/AndroidRuntime(19880): ... 9 more
06-07 01:58:10.919 W/ActivityManager(30573): Force finishing activity com.naquatic.monstercrafter/com.unity3d.player.UnityPlayerNativeActivity
原因在于java.lang.ClassCastException: g.u.CustomClassLoader cannot be cast to dalvik.system.BaseDexClassLoader,就是应用自定义的类加载器和BaseDexClassLoader类型不匹配,
这个提示在哪里产生的呢,可以看到
Common_throws.cc (art\runtime):
void ThrowClassCastException(mirror::Class* dest_type, mirror::Class* src_type) {
// ClassCastException
void ThrowClassCastException(mirror::Class* dest_type, mirror::Class* src_type) {
ThrowException("Ljava/lang/ClassCastException;", nullptr,
StringPrintf("%s cannot be cast to %s",
PrettyDescriptor(src_type).c_str(),
PrettyDescriptor(dest_type).c_str()).c_str());
}
是虚拟机的解释器抛出的异常,这里有几个可能的触发点,
Interpreter_goto_table_impl.cc (art\runtime\interpreter): ThrowClassCastException(c, obj->GetClass());
Interpreter_switch_impl.cc (art\runtime\interpreter): ThrowClassCastException(c, obj->GetClass());
Mterp.cc (art\runtime\interpreter\mterp): ThrowClassCastException(c, obj->GetClass());
先不进行虚拟机相关的分析(问题不在这里),再回头看log
06-07 01:58:10.910 E/AndroidRuntime(19880): Caused by: java.lang.ClassCastException: g.u.CustomClassLoader cannot be cast to dalvik.system.BaseDexClassLoader
06-07 01:58:10.910 E/AndroidRuntime(19880): at android.app.NativeActivity.onCreate(NativeActivity.java:164)
06-07 01:58:10.910 E/AndroidRuntime(19880): at com.unity3d.player.UnityPlayerNativeActivity.onCreate(Unknown Source)
看到异常抛出在这里 android.app.NativeActivity.onCreate(NativeActivity.java:164),看代码先,
164: BaseDexClassLoader classLoader = (BaseDexClassLoader) getClassLoader();
165: String path = classLoader.findLibrary(libname);
就是getClassLoader取类加载器的时候,强制转化为BaseDexClassLoader的时候出错了,需要应用自己来修改。
为什么android7.0之前没有问题? 参考android6.0和android4.4的代码,相同的地方用来加载lib的时候,原来没使用classloader
File libraryFile = new File(ai.applicationInfo.nativeLibraryDir,
System.mapLibraryName(libname));
if (libraryFile.exists()) {
path = libraryFile.getPath();
}