Android应用程序启动时出现阻塞GC分配问题的原因

4

最近我在从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
...

然后这样的日志会不断出现,直到程序完全停止响应。根据我在 这里这里 读到的信息,这种问题可能由于创建了太多对象而导致。然而,我遇到了这样的问题,并没有对代码进行任何更改就得到了工作良好的构建。我做的唯一一件事是创建了程序的发布 APK,但我理解它不太可能是原因。
我对程序进行了分析,显示主要分配的是 WeakHashMapSafeIterableMap 类(更详细的 图片在此)。不幸的是,我没有创建任何这些类的对象,但它们可能由我使用的库分配,这些库主要来自于 Jetpack libraries
我尝试增加堆大小,但并没有帮助。 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模拟器。

因此,是否有解决此问题的方法? 如果需要任何额外的分析或代码,我已经准备好提供它。

1个回答

2

幸运的是,我能够解决这个问题。经过一段时间的研究,我决定调试我的程序以查看有问题的部分。出乎意料的是,问题似乎在我使用的 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中创建的。

干得好,侦探! - Bink

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接