美文网首页
Android ANR,看完不慌

Android ANR,看完不慌

作者: 雨落川川 | 来源:发表于2020-09-11 17:39 被阅读0次

    隔壁部门做了一个评价器,就是一个jsp页面在安卓设备上一直运行,安卓原生部分的很简单,就是通过webview加载,打了个apk。最近用户反馈说在运行一段时间后,有时4-5个小时,有时10几个小时,再次点击页面就会出现程序无响应的情况。于是找到我这边给测试解决,说真的,我比较慌。

    a.自己提出了几个可能的问题:

    1.设备的问题(因为集中采购的是一些奇奇怪怪的设备)。


    不过从设备信息看,除了low一些,看不出啥问题。
    2.webview的问题,或相关settings没有配置。
    看一一下,他们打的包是用原生的webview,我比较习惯用腾讯x5内核的,就是这个 com.tencent.smtt.sdk.WebView
            webView = new WebView(getApplicationContext());
            webView.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            relativeLayout.addView(webView);
    

    WebSettings的相关配置也是添加的

      WebSettings s = webView.getSettings();
            s.setJavaScriptEnabled(true);
            s.setJavaScriptCanOpenWindowsAutomatically(true);
    
            @SuppressLint("SdCardPath") String path = "/data/data/" + context.getPackageName() + "/databases/";
            s.setAppCachePath(path);
            s.setAppCacheEnabled(true);
            s.setCacheMode(WebSettings.LOAD_NO_CACHE);
            s.setSaveFormData(true);
            s.setDomStorageEnabled(true);
    

    tWebChromeClient 及WebViewClient相关也是设置了的,看起来也没啥问题。

    3.页面的问题。
    页面不是我写的,没证据不能讲。

    b.自己提出了几个可能的问题

    假设被推翻,出问题的时间也没法确定,看来捷径是走不通了,只能从抓日志下手了,这里用了友盟统计的sdk去帮助完成这一步,等待两天之后,错误日志收获满满,还是比较兴奋的。



    待俺赶上前去,选取一条仔细观瞧,不由得一身冷汗,尴尬了,看不懂。
    莫慌,看不不要紧,根据指导原则猜猜也是有用的。

    ANR 顾名思义Application Not Response ,就是程序无响应,应用跑着跑着Duang的卡住了,无法响应用户的操作如触摸事件等等

    触发原因和分类,也就是指导原则

    触发ANR的原因

    • 应用进程自身引起
      例如:
      1.主线程阻塞、挂起、死循环
      2.应用进程的其他线程的CPU占用率高,使得主线程无法抢占到CPU时间片
    • 其他进程间接引起(误伤)
      例如:
      1.当前应用进程进行进程间通信请求其他进程,其他进程的操作长时间没有反馈
      2.其他进程的CPU占用率极高,使得当前应用进程无法抢占到CPU时间片

    ANR的分类:

    1. 应用在5秒内未响应用户的输入事件,如按键或触摸事件
    2. BroadcastReceiver未在10秒内完成相关的处理
    3. Service的各个生命周期函数时20秒内没有执行完毕
      接下来试着读读日志
    
    anr traces:
    
    generate begin time: 2020-09-10 08:40:39
    
    [DEBUG] dump art internal: 111
    
    [DEBUG] VMExt: 0xb4c7c000, i: 64, str: 3
    
    [DEBUG] runtime trace: 33,20,/data/anr/traces.txt
    
    [DEBUG] aborting: 0xb4bfde3c, 0
    
    [DEBUG] Dump: 0x0, State: 0xb4aed931, JavaStack: 0xb4ae878d
    
    [DEBUG] Thread spec key: 0xb4bff7fc
    
    [DEBUG] current: 0xb4cb6500, pid: 6495
    
    [DEBUG] List: 0xb4c6a800
    
    [DEBUG] Each: 0xb4af3b09
    
    [DEBUG] err: 0xb6d4ee44
    
    [DEBUG] begin each
    
    [DEBUG] dumping 0xb4cb6500 ...
    
    main prio=7 tid=1 Native
    
      | group= sCount=0 dsCount=0 obj=0x74bcc000 self=0xb4cb6500
    
      | sysTid=4068 nice=-4 cgrp=default sched=0/0 handle=0xb6f0cb34
    
      | state=? schedstat=( 0 0 0 ) utm=0 stm=0 core=0 HZ=100
    
      | stack=0xbe71d000-0xbe71f000 stackSize=8MB
    
      | held mutexes=
    
      at android.view.ThreadedRenderer.nSyncAndDrawFrame(Native method)
    
      at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:341)
    
      at android.view.ViewRootImpl.draw(ViewRootImpl.java:2620)
    
      at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2439)
    
      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2072)
    
      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1112)
    
    

    [DEBUG] runtime trace: 33,20,/data/anr/traces.txt这句告诉我们anr日志保存路径(没卵用)
    main prio=7 tid=1 Native main 表示主线程 prio线程优先级 tid不是线程的id,它是一个在Java虚拟机中用来实现线程锁的变量,随着线程的增减,这个变量的值是可能被复用的. Native不必多说。
    tid对应值解释说明


    后面一行
    group= sCount=0 dsCount=0 obj=0x74bcc000 self=0xb4cb6500
    

    group是线程组名称。sCount是此线程被挂起的次数,dsCount是线程被调试器挂起的次数,当一个进程被调试后,sCount会重置为0,调试完毕后sCount会根据是否被正常挂起增长,但是dsCount不会被重置为0,所以dsCount也可以用来判断这个线程是否被调试过。obj表示这个线程的Java对象的地址,self表示这个线程本身的地址。

    此后是线程的调度信息

     sysTid=4068 nice=-4 cgrp=default sched=0/0 handle=0xb6f0cb34
    

    sysTid是Linux下的内核线程id,nice是线程的调度优先级,sched分别标志了线程的调度策略和优先级,cgrp是调度属组,handle是线程的处理函数地址。

    然后是线程当前上下文信息
    state=S schedstat=( 303590361913 618664734427 651535 ) utm=19466 stm=10893 core=0
    state是调度状态;schedstat从 /proc/[pid]/task/[tid]/schedstat读出,三个值分别表示线程在cpu上执行的时间、线程的等待时间和线程执行的时间片长度,有的android内核版本不支持这项信息,得到的三个值都是0;utm是线程用户态下使用的时间值(单位是jiffies);stm是内核态下的调度时间值;core是最后执行这个线程的cpu核的序号。
    最后就是这个线程的调用栈信息。

     stack=0xbe71d000-0xbe71f000 stackSize=8MB
    

    看了日志文件,对于如何找出ANR的真正原因,还是一件难事,其实说难不难,文本冗长我们没必要弄懂每一行的意思,一般的,如果是我们的应用造成的anr,至少能够在这个文件里看到包名com.xxx.xx的表述,结合上下文分析应该不难,但我这个没找到。
    除了找应用信息,查找wating ,anr等关键字,因为anr的情况一般是让主线程做了很多耗时的操作,我这个是应用长驻的,放在柜台员前让办事用户再办完事情进行评价的,很简答的功能,原生并没有耗时操作,jsp页面问了问写的人员也没有做耗时操作,这就很奇怪。

    苦苦阅读这个anr日志时,事情出现了转机,外派员反馈另一个地区的设备是来自不同厂商的,出现问题后厂商过来给设备进行过处理,目前那一批设备是好的(为啥不早说),于是联系那边询问,做了什么骚操作,发来了一个文件夹:


    图片.png

    简单看了看,主要是给更新了WebViewGoogle_arm32.apk,手机上是见过这东西的,开发者选项下查看`webView实现'就能够看到,小米华为都有,然而我手里这台设备在设置里搜寻一圈都没有(什么鬼设备)



    果断把这玩意给打上去,之后在 “设置-->应用-->Android System WebView” 看到了这个东西,不知道是否会生效。
    继续打开评价器,静置一个晚上,看明日会不会有错误。就写到这里。

    相关文章

      网友评论

          本文标题:Android ANR,看完不慌

          本文链接:https://www.haomeiwen.com/subject/snovektx.html