众所周知,ANR问题一般不太容易解决。它是一种比较综合性的问题。往往涉及系统事件分发逻辑,ANR产生机制,BINDER机制,线程同步,CPU和内存使用等各方面。意思就是说,要分析ANR,你需要的知识非常多。
也就因此,很多人看着ANR问题感觉无从下手,日志中的很多说法都很抽象。
既然如此,我们在了解一些基础知识的基础上,再自己去写一下anr是不是可以??
手动写出的“问题代码”如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
Trace.beginSection("zhangkai");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.textView);
Log.d("kaijun", "onCreate: ");
mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("kaijun", "onClick: -----");
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.kaijun.compareapplication","com.kaijun.compareapplication.MyService"));
bindService(intent, mSc, Context.BIND_AUTO_CREATE);
}
});
waitForTenminute();
Trace.endSection();
}
waitForTenminute()的具体实现:
public void waitForTenminute() {
try {
Thread.sleep(10000);
Log.d("kaijun", "waitForTenminute: ----------------");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
我们要模拟的场景如下:
输入事件超时。
也就是说,我在activity的onCreate方法中执行耗时操作。执行时间10s,如果在执行的过程中,我们有事件输入的话,由于主线程正在执行耗时操作,也就无法响应我们的操作。如果执行无响应超过5s,也就报出anr了。
此处需要注意一点:
如果按照当前代码运行,点击进入app后,如果我们不对手机进行任何操作,则主线程执行完耗时操作后就正常进入activity,并不会报出超时。只有在此过程中我们输入事件,才会直接导致系统弹出anr弹框。
总结:有anr不一定弹框。
按照我们的操作:
- 先进入activity,此时界面白屏,因为activity的onCreate并未执行完毕,我们只能看到一个白框
- 然后,点击返回键,等待
- 5s后弹出错误弹框
日志:
04-19 19:19:42.724 1118 4309 I ActivityManager: Done dumping
04-19 19:19:42.724 1118 4309 I AnrManager: dumpStackTraces end!
04-19 19:19:42.776 1118 4309 I AnrManager: ANR in com.kaijun.binderclientapp (com.kaijun.binderclientapp/.MainActivity), time=369867387
04-19 19:19:42.776 1118 4309 I AnrManager: Reason: Input dispatching timed out (ActivityRecord{4ced468 u0 com.kaijun.binderclientapp/.MainActivity t255} does not have a focused window)
04-19 19:19:42.776 1118 4309 I AnrManager: Load: 17.45 / 15.63 / 15.33
04-19 19:19:42.776 1118 4309 I AnrManager: Android time :[2021-04-19 19:19:42.72] [369876.625]
从日志来看:
AnrManager: Reason: Input dispatching timed out (ActivityRecord{4ced468 u0 com.kaijun.binderclientapp/.MainActivity t255} does not have a focused window)
然后我们看/data/anr/目录下的trace文件。打开文件后直奔tid=1的线程,也就是主线程:
"main" prio=5 tid=1 Sleeping
| group="main" sCount=1 dsCount=0 flags=1 obj=0x70e44300 self=0xa8b04610
| sysTid=20309 nice=0 cgrp=default sched=0/0 handle=0xb18f6470
| state=S schedstat=( 2986803784 560166676 1224 ) utm=234 stm=64 core=1 HZ=100
| stack=0xbe073000-0xbe075000 stackSize=8192KB
| held mutexes=
at java.lang.Thread.sleep(Native method)
- sleeping on <0x0139d315> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:442)
- locked <0x0139d315> (a java.lang.Object)
at java.lang.Thread.sleep(Thread.java:358)
at com.kaijun.binderclientapp.MainActivity.waitForTenminute(MainActivity.java:107)
at com.kaijun.binderclientapp.MainActivity.onCreate(MainActivity.java:64)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3464)
可以看到,主线程处于sleep状态。跟我们的代码中的Thread.sleep一致。
通过这个问题,仔细想一下anr问题的分析思路是不是更清晰了一些?
另外,多关注日志。通过eventlog我们可以看一下输入事件响应超时类问题的超时时间:
04-19 19:50:20.665 1118 2302 I sysui_multi_action: [757,803,799,key_back_down,802,1]
04-19 19:50:25.467 1118 10558 I am_anr : [0,10425,com.kaijun.binderclientapp,550027078,Input dispatching timed out (ActivityRecord{e82260b u0 com.kaijun.binderclientapp/.MainActivity t263} does not have a focused window)]
并且日志中可以看到对应的trace文件在那个目录,具体是哪个文件:
04-19 19:50:26.178 1118 10558 I ActivityManager: Dumping to /data/anr/anr_2021-04-19-19-50-26-177
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)