android.os.MessageQueue.nativePollOnce 处的 ANR

发布于 2025-01-14 08:09:40 字数 945 浏览 0 评论 0原文

我们在应用程序的不同部分看到了此 ANR。 想了解导致此 ANR 的原因吗?

main (native): tid=1 systid=31940
#00 pc 0x5431c libc.so 
#01 pc 0x1313a5 libart.so 
#02 pc 0x2ab05b libart.so 
#03 pc 0x3659 libnativehelper.so 
#04 pc 0x9dee9 libandroid_runtime.so 
#05 pc 0x65c45 libgui.so 
#06 pc 0x11dcd libutils.so 
#07 pc 0x11abf libutils.so 
#08 pc 0xbcc7d libandroid_runtime.so 
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:339)
       at android.os.Looper.loop(Looper.java:199)
       at android.app.ActivityThread.main(ActivityThread.java:8276)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006)

这是 firebase 对于此 ANR 的说法 -

发生 ANR 时该线程处于空闲状态。我们没有足够的 确定根本原因的信息。

We are seeing this ANR in different parts of our app.
Wanted to understand what causes this ANR?

main (native): tid=1 systid=31940
#00 pc 0x5431c libc.so 
#01 pc 0x1313a5 libart.so 
#02 pc 0x2ab05b libart.so 
#03 pc 0x3659 libnativehelper.so 
#04 pc 0x9dee9 libandroid_runtime.so 
#05 pc 0x65c45 libgui.so 
#06 pc 0x11dcd libutils.so 
#07 pc 0x11abf libutils.so 
#08 pc 0xbcc7d libandroid_runtime.so 
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:339)
       at android.os.Looper.loop(Looper.java:199)
       at android.app.ActivityThread.main(ActivityThread.java:8276)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006)

This is what firebase has to say about this ANR -

This thread was idle when the ANR occurred. We don't have sufficient
information to determine the root cause.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

耳钉梦 2025-01-21 08:09:40

NativePollOnce:

当CPU等待新任务/消息时出现。

原因

  1. 如果BroadCast Receiver在10秒内没有完成执行,则可能会出现ANR。
  2. 输入事件5秒内无响应
  3. 当应用错误地尝试显示对话框但调用不是来自主线程时,可能会导致ANR。 (注意:验证UI线程中对UI View的所有调用)
  4. 这可能是由于内存泄漏而发生的。
  5. Handler.postDelayed 可能会产生问题
  6. 这种类型的崩溃很常见,当发生堆栈转储时,某些应用程序的堆栈跟踪可能会在实际 ANR 时间之后很长一段时间内转储
  7. 它可能发生在 SCREEN_ON BROADCAST 上,并且 google 广告正在使用 SCREEN_ON BROADCAST 。
  8. 它可能发生在垃圾收集过程中(由
    Ezequiel Adrian 评论)

收集 ANR 的方法

  1. WatchDog
  2. 捕获本机 SIGQUIT
  3. ApplicationExitInfo(由 crashalytics 使用)
  4. 从 Google Play Console
  5. Firebase 收集(Firebase 仅从 Android 11 及更高版本收集)

解决 ANR 的挑战:揭开

ANR 之谜的神秘面纱。 链接

解决方案:

  1. 优化初始化和广告加载。 链接
  2. 如果您正在使用 Media,则在 IO 线程中释放它
  3. 查找内存泄漏使用泄漏金丝雀或 Android 进行追踪
    profiler
  4. 将 firebase 降级到 28.4.2 (它不会收集 ANR,但并不意味着它不会发生)
  5. 验证 UI 线程中 UI View 的所有调用
  6. 更多信息来自 问题跟踪器
  7. 更多信息 Stack Ans
  8. 减少了 Static(java) 或伴随对象 (kotlin)、属性和类的使用

NativePollOnce:

It appears when the CPU is waiting for a new task/message.

Reasons:

  1. ANR may occur if BroadCast Receiver hasn’t finished execution within 10 Seconds.
  2. No response to an input event within 5 Seconds
  3. ANR may be caused when the app tries to show a dialog by mistake but the call is not from the main thread. (Note: verify all calls of UI View from UI thread)
  4. It may occur due to memory leaks.
  5. Handler.postDelayed may create an issue
  6. This type of crash is commonly seen, when the stack dump takes place, some app’s stack trace could be dumped for a long after the actual ANR time
  7. It may occur on SCREEN_ON BROADCAST and google ads are using SCREEN_ON BROADCAST.
  8. It may occur during the Garbage collection process (by
    Ezequiel Adrian comment)

Ways to collect ANRs:

  1. WatchDog
  2. Catching Native SIGQUIT
  3. ApplicationExitInfo (used by crashalytics)
  4. Collect from Google Play Console
  5. Firebase (firebase only collect from android 11 and above)

Challenges in Solving ANR:

Demystifying the ANRs Puzzle. Link

Solutions:

  1. Optimize initialization and Ad Loading. Link
  2. If you are using Media then release it in IO Thread
  3. Find memory leaks to track down using a leak canary or Android
    profiler
  4. Downgrade firebase to 28.4.2 (It will not collect ANR but it does not mean that it cannot occur)
  5. Verify all calls of UI View from the UI thread
  6. More Information from Issue Tracker
  7. More Info Stack Ans
  8. Reduced the usage of Static(java) or companion object(kotlin)'s, properties, and classes
迷迭香的记忆 2025-01-21 08:09:40

面临同样的问题 - 我读到它与 Admob 或统一广告相关,并且 google 有一个开放线程: https://issuetracker.google.com/issues/230950647?pli=1

Facing the same issue - I've read that it related to Admob or unity ads and there is an open thread for google : https://issuetracker.google.com/issues/230950647?pli=1

一影成城 2025-01-21 08:09:40

可能的原因:UI线程被同步屏障阻塞。

如果UI线程的MessageQueue有同步屏障,所有消息都会被阻塞(异步消息除外),直到同步屏障已移除。

什么会导致此问题?

如果您在非 UI 线程中使视图无效,则可能会遇到此问题。

为什么?

// View.java
public void invalidate() {
    invalidate(true);
}
public void invalidate(boolean invalidateCache) {
    invalidateInternal(...);
}
void invalidateInternal(...) {
    final ViewParent p = mParent;
    p.invalidateChild(this, damage);
}

// ViewGroup.java
public final void invalidateChild(View child, final Rect dirty) {
    onDescendantInvalidated(child, child);
}

public void onDescendantInvalidated(@NonNull View child, @NonNull View target) {
    //...
    if (mParent != null) {
        mParent.onDescendantInvalidated(this, target);
    }
}

ViewRootImpl 是最顶层的 ViewParent

public void onDescendantInvalidated(@NonNull View child, @NonNull View descendant) {
    // TODO: Re-enable after camera is fixed or consider targetSdk checking this
    // checkThread();
    invalidate();
}
void invalidate() {
    scheduleTraversals();
}
void scheduleTraversals() {
    if (!mTraversalScheduled) {
        mTraversalScheduled = true;
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
    }
}

void unscheduleTraversals() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
    }
}

void doTraversal() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
}

请注意上面代码片段中的 postSyncBarrierremoveSyncBarrier

ViewRootImplonDescendantInvalidated 中,它没有检查它是否在 UI 线程中。

因此,如果您偶尔在非 UI 线程中无效您的视图,您可能会在消息队列中留下同步屏障,而稍后不会被删除,然后您将得到这个 问题。

我是否在 ui 线程中使我的视图无效?

在我的例子中,我向许多视图提供了 BitmapDrawable,然后我可以更改 工作线程中 BitmapDrawable 的位图。这将导致使用 BitmapDrawable 的视图在工作线程中失效。

如何检查非 UI 线程中是否有任何视图无效?

在视图层次结构的最顶层 ViewGroup 中,覆盖 onDesendantInvalidated

override fun onDescendantInvalidated(child: View, target: View) {
    super.onDescendantInvalidated(child, target)
    if (Looper.getMainLooper() != Looper.myLooper()) {
        throw RuntimeException("no ui thread")
    }
}

< strong>问题典型症状

  1. RecyclerViewListView 可以正常滚动,但任何视图的点击监听器都不起作用。
  2. ANR 可能会在 CPU 过载较低且主线程的堆栈跟踪包含 MessageQueue.nativePollOnce 时发生,
  3. ANR 可能是 BroadcastTimeout anr 或 ServiceTimeout anr 但不是 KeyDispatchTimeout anr

A possible reason: The UI thread was blocked by sync barrier.

If MessageQueue of the UI thread has a sync barrier, all messages will be blocked (except asynchronous ones) until the sync barrier removed.

What will cause this issue?

If you invalidate your view in a Non-UI thread, you may get this issue.

Why?

// View.java
public void invalidate() {
    invalidate(true);
}
public void invalidate(boolean invalidateCache) {
    invalidateInternal(...);
}
void invalidateInternal(...) {
    final ViewParent p = mParent;
    p.invalidateChild(this, damage);
}

// ViewGroup.java
public final void invalidateChild(View child, final Rect dirty) {
    onDescendantInvalidated(child, child);
}

public void onDescendantInvalidated(@NonNull View child, @NonNull View target) {
    //...
    if (mParent != null) {
        mParent.onDescendantInvalidated(this, target);
    }
}

ViewRootImpl is the top-most ViewParent:

public void onDescendantInvalidated(@NonNull View child, @NonNull View descendant) {
    // TODO: Re-enable after camera is fixed or consider targetSdk checking this
    // checkThread();
    invalidate();
}
void invalidate() {
    scheduleTraversals();
}
void scheduleTraversals() {
    if (!mTraversalScheduled) {
        mTraversalScheduled = true;
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
    }
}

void unscheduleTraversals() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
    }
}

void doTraversal() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
}

Note the postSyncBarrier and removeSyncBarrier in the snippet above

Here in onDescendantInvalidated of ViewRootImpl, it didn't check if it's in UI thread.

So if you invalidate your view in a non-ui thread occasionally, you may leave a sync barrier in the message queue without being removed later and then you will get this issue.

Do I invalidate my view off ui thread?

In my case, I provide BitmapDrawables to many views and then I may change the bitmap of the BitmapDrawable in a work thread. This will cause the views using the BitmapDrawable being invalidated in the work thread.

How to check if any views is invalidated in non-ui thread?

In the top-most ViewGroup of your view hierarchy, override onDescendantInvalidated:

override fun onDescendantInvalidated(child: View, target: View) {
    super.onDescendantInvalidated(child, target)
    if (Looper.getMainLooper() != Looper.myLooper()) {
        throw RuntimeException("no ui thread")
    }
}

Typical symptoms of the issue

  1. RecyclerView or ListView can be scrolled normally, but click listeners of any view will not work.
  2. ANR may occurs with a low cpu overload and stack trace of the main thread contains MessageQueue.nativePollOnce
  3. The ANR may be a BroadcastTimeout anr or a ServiceTimeout anr but is NOT a KeyDispatchTimeout anr
别在捏我脸啦 2025-01-21 08:09:40

在最新版本的云消息传递依赖项 v23.0.7 Firebase 上,提及此版本可能会降低 ANR。以下是他在其文档中提到的一句话。

消息广播现在在绑定到服务后立即完成。此更改应该会减少 ANR 的几率

On the latest release of Cloud Messaging dependencies v23.0.7 Firebase Mention that this release might reduce the ANR. here is his words mentioned in its documentation.

Message broadcasts now finish immediately after binding to the service. This change should reduce the chance of ANRs

风筝有风,海豚有海 2025-01-21 08:09:40

就我而言,这是 firebase 云消息传递库中的错误。该错误已在2022年12月8日发布的最新版本23.1.1中修复。

https://firebase.google.com/support/release- Notes/android#messaging_v23-1-1

希望对您有帮助。

In my case, it was an error in the firebase cloud messaging lib. The bug was fixed in the latest version 23.1.1, which was released on 12/8/2022.

https://firebase.google.com/support/release-notes/android#messaging_v23-1-1

Hope it helps you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文