檢測ANR

檢測方式

線上環境的ANR錯誤需要我們及時的上報服務器,那麼如何主動檢測ANR錯誤呢?

1、FileObserver

當發生ANR的時候,我們查看控制檯的日誌

07-27 10:25:09.732 23995-24002/com.qunar.yuzhiyun.anr I/dalvikvm: threadid=3: reacting to signal 3
07-27 10:25:09.792 23995-24002/com.qunar.yuzhiyun.anr I/dalvikvm: Wrote stack traces to '/data/anr/traces.txt'

可以看出,發生ANR,進程會收到信號3,緊接着開始向’/data/anr/traces.txt’ 文件寫 棧跟蹤信息,這樣的話,我們只需要通過FileObserver 來監控’/data/anr/traces.txt’ 文件的變化不就行了嗎?只要有變化就說明發生了ANR(據筆者所知,暫時沒有其他引起traces.txt變化的原因)。但是FileObserver在5.0及以上系統部分機型失效,所以不算好的方法。

2、watchDog方式

有人提出watchDog方式的檢測方法,在主線程定義一個變量count,在子線程不斷的通知主線程去更新count的值(比如+=1),子線程維護一個值與count相等的變量,睡眠5秒後去判斷兩個值是否相等,從而判斷是否出現了ANR錯誤,以下代碼簡單的給出了示範。(讀者在運行這段代碼的時候,先點擊FloatingActionButton 讓主線程長時間睡眠,然後再操作一下界面的其他元素,就可以在控制檯看到Log.e(“Thread”,”ANR happpened”); 打印的日誌啦)

public class MainActivity extends AppCompatActivity {

    Handler handler=new Handler();
    int count;
    private final Runnable message= new Runnable() {
        @Override public void run() {
            count= (count+ 1) % 10;
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);


        new Thread(){
            @Override
            public void run() {
                int lastCount;
                while(true) {
                    lastCount =  count;
                    handler.post(message);
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(count == lastCount) {
                        //檢測到了ANR
                        Log.e("Thread","ANR happpened");
                    }
                }
            }
        }.start();
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                    try {
                        Log.i("Thread","start sleep");
                        Thread.sleep(1000000000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
        });
    }


}

參考

http://mobnav.dev.qunar.com/2016/08/29/anr_monitor_analysis/

http://mobnav.dev.qunar.com/2015/11/12/android-anr-monitor/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章