在过去的一周里,我收到了11个非常类似的anr。我试着分析它们,但我没能看到代码的哪一部分导致ANR。
下面是其中一个堆栈转储:http://pastebin.com/rC8f3fgr
我认为anr总是由阻塞主线程引起的。然而,在转储中,我甚至找不到应用程序的主线程(com.degoo.android)。
唯一的事情我发现有点可疑的是,几个线程正在等待libwebviewchromium.so。我们不使用Chrome的webview做任何事情。但是,我们确实支持通过Google的oauth机制登录。也许是使用webview?
我该如何分析这样的问题呢?这就是严格模式的作用:
if (DEVELOPER_MODE) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.penaltyLog()
.build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
}
一旦你启用了严格模式,应用程序就会卡在屏幕上,这会给UI线程带来更多的负载。
。
根据我的经验,anr是由涉及UI线程的死锁引起的。我猜你试图在anr开始之前同步你的应用程序使用资源的方式(如数据结构)。
我处理anr的最好方法:1. 在你的项目中搜索"synchronized("或"synchronized(")"(如果使用Android Studio,点击edit -> Search in file或在Eclipse中点击Search -> file)。2. 在每个同步块之前、内部和之后打印一些内容:
System.out.println("className.methodName() : capturing lock");
synchronized (lock) {
System.out.println("className.methodName() : lock captured");
...
}
System.out.println("className.methodName() : lock released");
- 运行并等待ANR。日志应该给你所有的数据,你需要知道什么时候和为什么这些anr发生。
当同步方法中有同步块时要非常小心——在我的例子中,这是导致死锁的原因,因为UI线程可以捕获类锁并等待某些锁被释放,但是应该释放该锁的线程等待一般类级别的锁被释放,这被UI线程捕获,因此死锁。如果确实是这种情况,您可能希望避免同步方法,而只依赖同步块。
希望有帮助