微信邦

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 5556|回复: 0

精神哥讲Crash(二):java.lang.NoSuchMethodError

[复制链接]
发表于 2015-1-5 15:54:34 | 显示全部楼层 |阅读模式
文章来源微信公众号:腾讯大学

      2015年第一个工作日,精神哥给大家分享的第二个Crash是“java.lang.NoSuchMethodError”。
      一、java.lang.NoSuchMethodError 基本介绍
      全名
      java.lang.NoSuchMethodError
      官方解释
      Thrown if an application tries to call a specified  method of a class (either static or instance), and that class no longer has a  definition of that method.
      意思就是程序找不到你要用的那个方法!
      影响力排名
      出错量排名第4
      精神哥点评
      抛出这异常,只能怪这个喜新厌旧、鱼龙混杂的社会!虽然是社会的错,但你不想办法解决它,就只能等屎了!
      java.lang.NoSuchMethodError问题的根本原因是开发编译时所依赖的环境,跟实际App运行的环境不匹配。
      

      二、错误场景分析
      1、你就喜欢搞新API,这么喜新厌旧!你家妞知道不?
      
      错误代码
      //检查该acitivity是否已经销毁
      public static boolean isActivityClose( Activity  activity){
      if(activity != null){
      return activity.isDestroyed();
      }
      return false ;
      }
      编译环境
      Android 4.2 SDK( API LEVEL 17
      运行环境
      Android 4.0 设备( API LEVEL 14
      期望结果
      正确返回activity是否已经销毁。
      实际结果
      Crash!!
      java.lang.NoSuchMethodError:com.tencent.bugly.crashreport.test.MainActivity.isDestroyed
      原因分析
      Activity.isDestroyed()方法是Android 4.2增加的,在这之前的系统肯定找不到这个方法,所以在4.2之前的设备上都会Crash!
      解决方法
      调用时对当前系统API LEVEL做判断,如果小于17就放弃调用
      修复代码
      public Boolean isActivityClose( Activity activity){
      if(Build.VERSION.SDK_INT )
      return null;
      if(activity != null){
      return activity.isDestroyed();
      }
      return false ;
      }
      
      2、@Deprecated的API厂家最爱删,你竟然敢用?
      API标志
      @Deprecated标注的API
      标志描述
      Annotation type used to mark program elements that  should no longer be used by programmers.
      这个API后面随时会被干掉!
      现状描述
      谷歌还是比较小心的,精神哥发现Android的SDK及Android的亲儿子设备上,这些@Deprecated的API基本上都保留了,谷歌最多就是置空实现或直接抛出一个非法访问的异常,所以开发过程中并没有感觉到API过期不能用(当然有警告啦)
      但谷歌亲儿子设备只占Android设备的冰山一角,很多厂家可没管那么多,为了尽可能的节省资源,大刀阔斧的对API进行裁剪,而这个@Deprecated的API就是最有理由被干掉的,所以出现大量的java.lang.NoSuchMethodError的Crash!
      

      3、@Hide的API是人家谷歌私有的,删改都不会跟你商量的,你还敢用吗?
      
      API标志
      @Hide标注的API
      标志描述
      When applied to a package, class, method or field,  @hide removes that node and all of its children from the documentation.
      这个API压根不想让你看到,更别说让你使用了。
      现状描述
      由于Android的开源,加上Java的反射机制的便利,开发者总是喜欢研究源码,用注入或反射的方式获取到官方未正式开放的能力。这很有效,但也很危险,因为谷歌随时会调整,会导致你的App出现各种诡异的java.lang.NoSuchMethodError!
      很多同学认为public的私有API,谷歌不会乱改,可以大胆的用。
      精神哥,随手给你挑一个反例来证明你的天真:
      android.content.pm.PackageParser(该类用于apk安装包内容解析,很受欢迎)这个私有类的public构造函数在5.0发生变化了,而之前一直没变过。
      //5.0以前有String作为参数,用于传入apk路径
      public PackageParser(String archiveSourcePath) {
      mArchiveSourcePath = archiveSourcePath;
      }
      //5.0优化成无参实现了,一个对象可以多次解析了
      public PackageParser() {
      mMetrics = new DisplayMetrics();
      mMetrics.setToDefaults();
      }
      想看PackageParser.java源码又懒得找的同学,公众号里@精神哥,我给你发哈!
      
      java.lang.NoSuchMethodError在Bugly影响力排行榜中稳居第4,就能看出Android程序员所面对的Android市场,碎片化有多么的严峻了!
      
      精神哥想不出可以一劳永逸的解决方法,在这里再给大家总结几个私人建议(欢迎拍砖):
      o    开发阶段用Android Lint,静态检查代码中API兼容性。
      o    预发布前用Bita ( bita.qq.com 腾讯云测试平台),动态检测主流真机的兼容性。
      o    使用腾讯Bugly( bugly.qq.com 腾讯Bugly),实时掌握应用在真实用户环境中的遗留问题。
      
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

微信邦网联系QQ|Archiver|手机版|小黑屋|鲁公网安备 37082802000167号|微信邦 ( 鲁ICP备19043418号-5 )

GMT+8, 2024-9-20 01:05 , Processed in 0.067558 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2013 Wxuse Inc. | Style by ytl QQ:1400069288

快速回复 返回顶部 返回列表