Android NoClassDefFoundError 之 PersistableBundle

今天测试反馈,在应用在华为麦芒上出现了闪退,找了台类似的低端机,复现了问题

E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.NoClassDefFoundError: android/os/PersistableBundle
at java.lang.Class.getDeclaredMethods(Native Method)
at java.lang.Class.getPublicMethodsRecursive(Class.java:955)
at java.lang.Class.getMethods(Class.java:938)
at org.greenrobot.eventbus.SubscriberMethodFinder.findUsingReflectionInSingleClass(SubscriberMethodFinder.java:157)
at org.greenrobot.eventbus.SubscriberMethodFinder.findUsingInfo(SubscriberMethodFinder.java:88)
at org.greenrobot.eventbus.SubscriberMethodFinder.findSubscriberMethods(SubscriberMethodFinder.java:64)
at org.greenrobot.eventbus.EventBus.register(EventBus.java:136)
at com.mx.engine.event.EventProxy.register(EventProxy.java:44)
at com.mx.framework2.view.ui.BaseActivity.init(BaseActivity.java:139)
at com.mx.framework2.view.ui.BaseActivity.onCreate(BaseActivity.java:130)
at com.gome.common.base.GBaseActivity.onCreate(GBaseActivity.kt:27)
at android.app.Activity.performCreate(Activity.java:5043)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2033)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2094)
at android.app.ActivityThread.access$600(ActivityThread.java:134)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1202)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4777)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:764)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:531)
at dalvik.system.NativeStart.main(Native Method)

在错误信息中,出现了EventBus的身影,因此直奔github eventbus,在issues搜索PersistableBundle关键词,找到了网友提交的类似情形 https://github.com/greenrobot/EventBus/issues/156
官方解释了该问题出现的原因(http://greenrobot.org/eventbus/documentation/faq/)

class PersistableBundle was added in API level 21. Along with the new class some new life cycle methods were introduced in the class Activity having PersistableBundle as a parameter, for example onCreate (Bundle savedInstanceState, PersistableBundle persistentState). Now, if you override this method and you try to register this Activity to EventBus on a older device, we have exactly the scenario described to cause to bug. Understanding why this happens will help to resolve the issue easilyclass PersistableBundle was added in API level 21. Along with the new class some new life cycle methods were introduced in the class Activity having PersistableBundle as a parameter, for example [onCreate (Bundle savedInstanceState, PersistableBundle persistentState)](http://developer.android.com/intl/in/reference/android/app/Activity.html#onCreate(android.os.Bundle, android.os.PersistableBundle)). Now, if you override this method and you try to register this Activity to EventBus on a older device, we have exactly the scenario described to cause to bug. Understanding why this happens will help to resolve the issue easily

在android5.0中引入了PersistableBundle,在Activity的一些生命周期的方法中,增加了PersistableBundle类型形参,比如

protected void onCreate(@Nullable Bundle savedInstanceState){
      super.onCreate(savedInstanceState);
}

public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
      onCreate(savedInstanceState);
}

protected void onRestoreInstanceState(Bundle savedInstanceState) {
      if (mWindow != null) {
            Bundle windowState = savedInstanceState.getBundle(WINDOW_HIERARCHY_TAG);
            if (windowState != null) {
                   mWindow.restoreHierarchyState(windowState);
            }
      }
 }

public void onRestoreInstanceState(Bundle savedInstanceState, PersistableBundle persistentState) {
      if (savedInstanceState != null) {
             onRestoreInstanceState(savedInstanceState);
      }
 }

对比可以发现,相同名称的生命周期方法,带PersistableBundle的方法修饰符为public,而我们常重载的为protected。EventBus通过反射来获取注册类所有的订阅方法,考虑到效率问题,会调用Class.getDeclaredMethods(),也是就public方法,如果重载了含有PersistableBundle的方法,EventBus在类初始化的时候会访问该方法,在系统版本低于Android5.0的手机上,就会因为找不到PersistableBundle.class而抛出异常
仔细检查了项目代码,果然重载了父类的带PersistableBundle的生命周期方法,去掉PersistableBundle,crash消失了

EventBus register方法代码片段

修改之前代码

修改之后代码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 176,037评论 25 709
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,751评论 2 45
  • 江水三千里,家书十五行。行行无别语,只道早还乡。
    李尔王阅读 1,670评论 1 1
  • 打开手机发现微信和QQ里面每天都有很多刷世界杯的一些“球迷们”,在感叹和惋惜中迎来了半决赛,我也和朋友们随...
    zcmorlen阅读 1,346评论 0 1

友情链接更多精彩内容