android 权限询问 Anr,Android ANR初探

前言

记得之前换工作面试的时候,面试官问我知道ANR吗?我说知道,然后让我讲了一下ANR出现的原因,我就把ANR出现的原因一通说。然后,面试官又问我那么怎么分析和解决ANR问题呢?这时候我就傻眼了,只能说分析代码了。然后面试官笑了一下,又问我:那么你知道ANR会生成一个ANR文件吗?当时的我该怎么形容呢?硬着头皮说不知道。当然,那次也就GG了。

首先

那么什么是ANR呢?

1、解释

Application Not Responding即应用无响应。

当操作在一段时间内,系统无法处理是,就会发生ANR。弹出对应的无响应的对话框。

2、ANR的类型

1)KeyDispatchTimeout

这个Key事件分发超时的时间,Android默认是5秒,主要是定义在ActivityManagerService.java

// How long we wait until we timeout on key dispatching.

static final int KEY_DISPATCHING_TIMEOUT = 5*1000;

2)BroadcastTimeOut

广播的超时时间,分为FG和BG,分别是10秒和60秒。同样是定义在ActivitManagerService.java

// How long we allow a receiver to run before giving up on it.

static final int BROADCAST_FG_TIMEOUT = 10*1000;

static final int BROADCAST_BG_TIMEOUT = 60*1000;

3)ServiceTimeOut

Service的超时时间为20秒,定义在ActiveServices.java

// How long we wait for a service to finish executing.

static final int SERVICE_TIMEOUT = 20*1000;

// How long we wait for a service to finish executing.

static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;

其次

上面说了那么多,那么我们来模拟一下ANR并且分析一下

1、首先创建一个activity,里面放两个按钮,当我们点击选择相册的按钮的时候先让主线程休眠50s,然后看看

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

btn_album.setOnClickListener {

Thread.sleep(50*1000)

CameraUtil.openAlbum(this, REQUEST_CODE_OPEN_PHOTO_ALBUM)

}

btn_take_photo.setOnClickListener {

CameraUtil.takePhoto(this, REQUEST_CODE_TAKE_PHOTO)

}

}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

super.onActivityResult(requestCode, resultCode, data)

CameraUtil.onActivityResult(

this,

requestCode,

resultCode,

data,

object : CameraUtil.OnCameraResultListener {

override fun onAlbumResult(path: String) {

Log.e("TAG", path)

}

override fun onCameraResult(uri: Uri) {

Log.e("TAG", uri.toString())

}

})

}

}

7f1710fdefeb

ANR.png

分析:可以看到上面我们在主线程中让主线程休眠50s,那么界面长时间无响应就会出现ANR了,如上图所示。那么当我们不知道为什么会出现ANR的时候该怎么处理呢?其实,当出现ANR的时候会在data/anr/目录下生成anr日志文件,这里以as为例。

7f1710fdefeb

ANR文件.png

1、如上图所示,我们先点击DeviceFile Explorer选项,然后打开data/anr文件,里面的anr_2020-08-10-18-17-42就是我们所需要的anr文件。然后,右击保存到电脑上,找到我们保存的地方打开ANR文件看看里面的具体内容。

2、ANR文件具体内容

suspend all histogram: Sum: 1.413ms 99% C.I. 2us-243.199us Avg: 13.586us Max: 352us

DALVIK THREADS (16):

"Signal Catcher" daemon prio=5 tid=3 Runnable

| group="system" sCount=0 dsCount=0 flags=0 obj=0x15700020 self=0x7b7b016400

| sysTid=13715 nice=0 cgrp=default sched=0/0 handle=0x7b5c6054f0

| state=R schedstat=( 30247917 1431772 18 ) utm=1 stm=1 core=0 HZ=100

| stack=0x7b5c50a000-0x7b5c50c000 stackSize=1009KB

| held mutexes= "mutator lock"(shared held)

native: #00 pc 00000000003c7d4c /system/lib64/libart.so (art::DumpNativeStack(std::__1::basic_ostream>&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+220)

native: #01 pc 00000000004a5b64 /system/lib64/libart.so (art::Thread::DumpStack(std::__1::basic_ostream>&, bool, BacktraceMap*, bool) const+352)

native: #02 pc 00000000004bf780 /system/lib64/libart.so (art::DumpCheckpoint::Run(art::Thread*)+844)

native: #03 pc 00000000004b84fc /system/lib64/libart.so (art::ThreadList::RunCheckpoint(art::Closure*, art::Closure*)+484)

native: #04 pc 00000000004b798c /system/lib64/libart.so (art::ThreadList::Dump(std::__1::basic_ostream>&, bool)+1036)

native: #05 pc 00000000004b74ac /system/lib64/libart.so (art::ThreadList::DumpForSigQuit(std::__1::basic_ostream>&)+884)

native: #06 pc 00000000004878a0 /system/lib64/libart.so (art::Runtime::DumpForSigQuit(std::__1::basic_ostream>&)+188)

native: #07 pc 0000000000493610 /system/lib64/libart.so (art::SignalCatcher::HandleSigQuit()+1372)

native: #08 pc 00000000004922e8 /system/lib64/libart.so (art::SignalCatcher::Run(void*)+256)

native: #09 pc 0000000000082e10 /system/lib64/libc.so (__pthread_start(void*)+36)

native: #10 pc 0000000000024080 /system/lib64/libc.so (__start_thread+68)

(no managed stack frames)

"main" prio=5 tid=1 Sleeping

| group="main" sCount=1 dsCount=0 flags=1 obj=0x75771ba0 self=0x7b7b014c00

| sysTid=13709 nice=-10 cgrp=default sched=0/0 handle=0x7c0184d548

| state=S schedstat=( 569303132 16322390 301 ) utm=51 stm=5 core=2 HZ=100

| stack=0x7ff5ac9000-0x7ff5acb000 stackSize=8MB

| held mutexes=

at java.lang.Thread.sleep(Native method)

- sleeping on <0x0808d0f6> (a java.lang.Object)

at java.lang.Thread.sleep(Thread.java:386)

- locked <0x0808d0f6> (a java.lang.Object)

at java.lang.Thread.sleep(Thread.java:327)

at com.yk.silence.customcamera.MainActivity$onCreate$1.onClick(MainActivity.kt:18)

at android.view.View.performClick(View.java:6652)

at android.view.View.performClickInternal(View.java:6624)

at android.view.View.access$3100(View.java:787)

at android.view.View$PerformClick.run(View.java:26213)

at android.os.Handler.handleCallback(Handler.java:891)

at android.os.Handler.dispatchMessage(Handler.java:102)

at android.os.Looper.loop(Looper.java:207)

at android.app.ActivityThread.main(ActivityThread.java:7470)

at java.lang.reflect.Method.invoke(Native method)

at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)

at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)

"Jit thread pool worker thread 0" daemon prio=5 tid=2 Native

| group="main" sCount=1 dsCount=0 flags=1 obj=0x156c0030 self=0x7b72033000

| sysTid=13714 nice=9 cgrp=default sched=0/0 handle=0x7b5c7064f0

| state=S schedstat=( 75499990 5454172 203 ) utm=5 stm=2 core=1 HZ=100

| stack=0x7b5c608000-0x7b5c60a000 stackSize=1021KB

| held mutexes=

kernel: (couldn't read /proc/self/task/13714/stack stderr:Permission denied)

native: #00 pc 000000000001f3ec /system/lib64/libc.so (syscall+28)

native: #01 pc 00000000000dbd94 /system/lib64/libart.so (art::ConditionVariable::WaitHoldingLocks(art::Thread*)+148)

native: #02 pc 00000000004c0fc4 /system/lib64/libart.so (art::ThreadPool::GetTask(art::Thread*)+260)

native: #03 pc 00000000004c052c /system/lib64/libart.so (art::ThreadPoolWorker::Run()+124)

native: #04 pc 00000000004bffec /system/lib64/libart.so (art::ThreadPoolWorker::Callback(void*)+148)

native: #05 pc 0000000000082e10 /system/lib64/libc.so (__pthread_start(void*)+36)

native: #06 pc 0000000000024080 /system/lib64/libc.so (__start_thread+68)

(no managed stack frames)

分析:既然我们已经拿到了ANR日志文件的内容了,那么怎么分析呢?不可能一通乱找吧。这个是当然的,有两个可以参考的点,一个就是我们应用程序的包名,另外一个就是main方法。这里我截取了一部分主要的日志文件,但是也够了。我们首先看一下"main"方法,并且找一下我们应用对应的包名com.yk.silence.customcamera,那么很容易就定位到了at com.yk.silence.customcamera.MainActivity$onCreate$1.onClick(MainActivity.kt:18),这一行,然后我们看一下我们的源码。在第18行的休眠50S的代码,所以找对应规律会事半功倍。

7f1710fdefeb

image.png

最后

好了,这个就是关于ANR初探的文章,如果有写的不到位的地方还请大佬不吝赐教。当然,如果你有更好的建议欢迎进群(493180098)探讨。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值