偶尔出现ClassCastException,在启动插件activity的时候
FATAL EXCEPTION: main Process: com.seuic.kysy:takedeliveryplugin, PID: 7107 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.seuic.kysy/com.example.my_runtime.TakeDeliveryPluginSingleTop1ProxyActivity}: java.lang.RuntimeException: java.lang.ClassCastException: com.kye.pad.takeDeliverybusiness.waybillform.WayBillFormActivity cannot be cast to com.tencent.shadow.core.runtime.PluginActivity at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2724) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527) at android.os.Handler.dispatchMessage(Handler.java:110) at android.os.Looper.loop(Looper.java:203) at android.app.ActivityThread.main(ActivityThread.java:6247) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924) Caused by: java.lang.RuntimeException: java.lang.ClassCastException: com.kye.pad.takeDeliverybusiness.waybillform.WayBillFormActivity cannot be cast to com.tencent.shadow.core.runtime.PluginActivity at com.tencent.shadow.core.loader.delegates.ShadowActivityDelegate.onCreate() at com.tencent.shadow.core.runtime.container.PluginContainerActivity.onCreate(PluginContainerActivity.java:84) at android.app.Activity.performCreate(Activity.java:6666) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2677)
这种类偶尔不能cast to父类的问题出现的场景,一般是父类由两个不同的ClassLoader加载的,所以是不同的类。
建议先检查一下自己修改的代码是否有ClassLoader相关的改动。以及com.tencent.shadow.core.runtime是否打包在多个apk中。
检查了没有改ClassLoader相关的代码,现在我有两个插件A跟B,com.tencent.shadow.core.runtime会分别打包到A跟B的apk中,如果这个会引起ClassCastException异常,大佬有什么解决办法吗
runtime不应该打包在插件中的。可以参考sample中的设置,用compileOnly方式依赖。
https://github.com/Tencent/Shadow/blob/a335b1906cfba3c6de129bad15e66c930288de83/projects/sample/maven/plugin-project/plugin-shadow-apk/build.gradle#L14
已经改成 compileOnly "com.tencent.shadow.core:runtime:$shadow_version" 方式还是会出现java.lang.ClassCastException 堆栈信息: java.lang.ClassCastException: com.kye.pad.takeDeliverybusiness.waybillform.WayBillFormActivity cannot be cast to com.tencent.shadow.core.runtime.PluginActivity com.tencent.shadow.core.runtime.PluginActivity.get(PluginActivity.java:36) com.tencent.shadow.core.runtime.ShadowActivityLifecycleCallbacks$Wrapper.getPluginActivity(ShadowActivityLifecycleCallbacks.java:107) com.tencent.shadow.core.runtime.ShadowActivityLifecycleCallbacks$Wrapper.onActivityCreated(ShadowActivityLifecycleCallbacks.java:115) android.app.Application.dispatchActivityCreated(Application.java:197) android.app.Activity.onCreate(Activity.java:963) com.tencent.shadow.core.runtime.container.GeneratedPluginContainerActivity.superOnCreate(GeneratedPluginContainerActivity.java:1470) com.tencent.shadow.core.runtime.container.PluginContainerActivity.superOnCreate(PluginContainerActivity.java:38) com.tencent.shadow.core.runtime.GeneratedPluginActivity.onCreate(GeneratedPluginActivity.java:402) androidx.core.app.ComponentActivity.onCreate(ComponentActivity.java:75) androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:335) androidx.appcompat.app.AppCompatActivity.onCreate(AppCompatActivity.java:85) com.trello.rxlifecycle2.components.support.RxAppCompatActivity.onCreate(RxAppCompatActivity.java:59) com.kye.pad.base.BaseActivity.onCreate(BaseActivity.java:237) com.kye.pad.base.baseabstract.AbstractActivity.onCreate(AbstractActivity.java:45) com.kye.pad.base.BaseBuryActivity.onCreate(BaseBuryActivity.java:41) com.kye.pad.takeDeliverybusiness.waybillform.WayBillFormActivity.onCreate(WayBillFormActivity.java:319) com.tencent.shadow.core.loader.delegates.ShadowActivityDelegate.onCreate() com.tencent.shadow.core.runtime.container.PluginContainerActivity.onCreate(PluginContainerActivity.java:84) android.app.Activity.performCreate(Activity.java:6666) android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2677) android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2789) android.app.ActivityThread.-wrap12(ActivityThread.java) android.app.ActivityThread$H.handleMessage(ActivityThread.java:1527) android.os.Handler.dispatchMessage(Handler.java:110) android.os.Looper.loop(Looper.java:203) android.app.ActivityThread.main(ActivityThread.java:6247) java.lang.reflect.Method.invoke(Native Method) com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063) com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
源码报错的地方 : static PluginActivity get(PluginContainerActivity pluginContainerActivity) { Object o = pluginContainerActivity.getPluginActivity(); if (o != null) { return (PluginActivity) o; } else { //在遇到IllegalIntent时hostActivityDelegate==null。需要返回一个空的Activity避免Crash。 return new ShadowActivity(); } } 这一句报 return (PluginActivity) o的异常,看了创建的地方,也没发现什么问题:
val pluginActivity = mAppComponentFactory.instantiateActivity( mPluginClassLoader, pluginActivityClassName, mHostActivityDelegator.intent ) initPluginActivity(pluginActivity, pluginActivityInfo) super.pluginActivity = pluginActivity
ClassLoader相关的代码没有改动过
那可以进一步看一下WayBillFormActivity是不是哪里的代码动态加载的类,它可能没被Transform编辑过。如果apk里打包了的话,可以反编译确认一下。
我遇到了相同的情况。我的场景的原因是插件同时(100-200ms内)进入了两次,导致加载了两次Loader(自然就出现了两个ClassLoader加载同一个类,强转然后就异常了)。我的解决方法是对FastPluginManager#loadePlugin方法做一个同步,等待上次插件加载完成再判断是否需要加载。其实也可以业务保证不连续调用插件进入,不过这并不优雅。