【问题标题】:The cause of blocking GC Allocation problem when starting an Android application启动Android应用时阻塞GC Allocation问题的原因
【发布时间】:2020-09-30 23:27:34
【问题描述】:

我最近在从 Android Studio 启动我的应用程序时遇到了垃圾收集器分配的异常问题。我的代码编译没有错误,程序不会在运行时抛出任何异常。然而,当我启动我的程序时,它没有响应。

我的 Logcat 显示:

2020-06-11 12:56:02.724 6246-6246/com.example.fragmentsdrawer W/art: Long monitor contention with owner ReferenceQueueDaemon (6254) at void java.lang.ref.ReferenceQueue.enqueuePending(java.lang.ref.Reference)(ReferenceQueue.java:234) waiters=0 in java.lang.ref.Reference java.lang.ref.ReferenceQueue.poll() for 221ms
2020-06-11 12:56:04.081 6246-6246/com.example.fragmentsdrawer I/art: Waiting for a blocking GC Alloc
2020-06-11 12:56:04.359 6246-6257/com.example.fragmentsdrawer I/art: Background partial concurrent mark sweep GC freed 1762218(55MB) AllocSpace objects, 0(0B) LOS objects, 18% free, 71MB/87MB, paused 94.394ms total 1.850s
2020-06-11 12:56:04.360 6246-6246/com.example.fragmentsdrawer I/art: WaitForGcToComplete blocked for 278.777ms for cause Alloc
2020-06-11 12:56:04.360 6246-6246/com.example.fragmentsdrawer I/art: Starting a blocking GC Alloc
2020-06-11 12:56:05.459 6246-6246/com.example.fragmentsdrawer I/art: Waiting for a blocking GC Alloc
2020-06-11 12:56:05.920 6246-6257/com.example.fragmentsdrawer I/art: Background sticky concurrent mark sweep GC freed 908419(20MB) AllocSpace objects, 0(0B) LOS objects, 0% free, 106MB/106MB, paused 77.434ms total 1.067s
2020-06-11 12:56:05.920 6246-6246/com.example.fragmentsdrawer I/art: WaitForGcToComplete blocked for 460.437ms for cause Alloc
2020-06-11 12:56:05.920 6246-6246/com.example.fragmentsdrawer I/art: Starting a blocking GC Alloc
2020-06-11 12:56:06.663 6246-6246/com.example.fragmentsdrawer I/art: Waiting for a blocking GC Alloc
...

然后这样的日志反复出现,直到程序完全停止响应。当我阅读 herehere 时,这样的问题可能是由创建的许多对象引起的。但是,在没有对代码进行任何更改的情况下,我在工作构建中遇到了这样的问题。我唯一做的就是创建了我的程序的发布 APK,但我知道这不太可能是原因。

我对程序进行了概要分析,结果显示,主要分配用于 WeakHashMapSafeIterableMap 类(更详细的 image is here )。不幸的是,我没有创建这些类的任何对象,但它们可能是由我正在使用的库分配的,这些库主要来自 Jetpack 库

我尝试增加堆大小,但没有帮助。

gradle.properties:

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m

build.gradle(用于模块:app)

android {
    ...
    dexOptions {
        javaMaxHeapSize "1536m"
    }
}

另外,我正在使用 Nox 模拟器。

那么,有什么办法可以解决这个问题吗?如果需要任何额外的配置文件或代码,我已准备好提供。

【问题讨论】:

    标签: java android garbage-collection


    【解决方案1】:

    幸运的是,我能够解决这个问题。经过一段时间的研究,我决定调试我的程序以查看有问题的部分。出乎意料的是,问题似乎出在我使用的LiveData 中。正如它所分析的那样,已经分配了大量的Iterator 对象。更准确地说,它在 void dispatchingValue(ObserverWrapper ...)方法:

    // LiveData method
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
            if (mDispatchingValue) {
                mDispatchInvalidated = true;
                return;
            }
            mDispatchingValue = true;
            do {
                mDispatchInvalidated = false;
                if (initiator != null) {
                    considerNotify(initiator);
                    initiator = null;
                } else {
                    // Too many allocations here
                    for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                            mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                        considerNotify(iterator.next().getValue());
                        if (mDispatchInvalidated) {
                            break;
                        }
                    }
                }
            } while (mDispatchInvalidated);
            mDispatchingValue = false;
    }
    

    在我的一个片段中,我将MutableLiveData 的值设置为null。它导致dispatchingValue() 方法中的无限循环。这就是为什么我的分析器显示了太多 WeakHashMap 对象,这些对象实际上是在 LiveData 中创建的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-30
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-26
      相关资源
      最近更新 更多