"Background concurrent copying GC freed" 条日志消息后空闲时应用冻结

App freezes when idle after "Background concurrent copying GC freed" log messages

重现问题的步骤:

我重现这个问题的方法是

  1. 我 运行 我的 android 应用程序 & 我进入 MainActivity
  2. 我让 phone 闲置了大约十分钟或更长时间,并在其设置中将设备配置为在闲置少于 30 分钟时不休眠。
  3. 在等待期间,在 Android Studio 的“运行”选项卡中,我看到如下消息:

Background concurrent copying GC freed 237478(18MB) AllocSpace objects, 52(1756KB) LOS objects, 69% free, 5507KB/17MB, paused 217us total 164.170ms

  1. 像上面那样发了 5 到 10 条消息后,我看到了这两条消息:

Background concurrent copying GC freed 257288(11MB) AllocSpace objects, 0(0B) LOS objects, 66% free, 6204KB/18MB, paused 86us total 165.671ms

Background young concurrent copying GC freed 217214(10MB) AllocSpace objects, 0(0B) LOS objects, 56% free, 8108KB/18MB, paused 112us total 129.379ms

  1. 如果我再等一段时间,我会不断收到上面的几条消息,如果我触摸屏幕,则没有任何可交互的东西,整个应用程序似乎被冻结了。此外,设备的“主页”和“返回”按钮没有任何作用。如果我在尝试再次最大化应用程序时将其最小化,则会出现很大的延迟,并且当应用程序最终打开时,一切都没有响应(按钮不执行任何操作,您甚至无法滚动)。所以,我不得不杀了这个应用程序。

观察与笔记:

我的结论:

我观察到,当我收到上述日志消息时,可用内存百分比逐渐降低,应用程序在达到低于 60% 的值时开始冻结。因此,我假设设备的内存无法处理那么多数据,这就是垃圾收集器不断重新分配内存以进行优化的原因。当然,最简单的解决方案是拥有更多内存的设备或使用更少和更小尺寸的图像,但我更喜欢更强大的解决方案。

问题:

  1. 我想知道是否有其他人在他们的应用程序中观察到这种行为,以及他们是如何处理的。

  2. 一开始我收到以“后台并发复制 GC 已释放”开头的日志消息(请参阅第 3 步),在收到一堆消息后我会收到几条消息(请参阅第 4 步),其中第一条消息以“后台并发复制 GC 已释放”开头,第二条消息以“后台年轻并发复制 GC 已释放”开头。 "young concurrent" 有什么不同的意思吗?还是我应该忽略这个变化?

  3. 有没有其他工具可以帮助我进一步调查此事?

我解决了这个问题,原来我的一个同事创建了一个新线程,即使在空闲时也一直保持活动状态。结果出现了“Background young concurrent copying GC freed”的消息,设备逐渐启动运行 out of memory。因此,对于观察到相同消息或行为的任何人,我建议他们分析检查其应用程序的内存消耗,尤其是多线程功能。

当同样的情况发生在我身上时,我注意到当我再次尝试使用我的 ListenerRegistrations 时正在监听 firebase 中的数据 例如;

private var dataListener: ListenerRegistration? = null

在定义了

形式后操作这个对象之前
dataListener?.remove()
dataListener= null

去做吧。现在您可以再次使用此对象用于不同或相同的目的