java - 应用程序在“后台并发复制 GC 释放”日志消息后空闲时冻结
问题描述
重现问题的步骤:
我重现此问题的方式是
- 我运行我的 android 应用程序并进入 MainActivity
- 我让手机闲置了大约十分钟或更长时间,在其设置中将设备配置为如果闲置时间少于 30 分钟则不休眠。
- 等待时,在 Android Studio 的“运行”选项卡中,我看到如下消息:
后台并发复制GC释放237478(18MB)个AllocSpace对象,52(1756KB)个LOS对象,69%空闲,5507KB/17MB,暂停217us共164.170ms
- 在上述 5 到 10 条消息之后,我看到了这两条消息:
后台并发复制GC释放257288(11MB)个AllocSpace对象,0(0B)个LOS对象,66%空闲,6204KB/18MB,暂停86us共165.671ms
后台年轻并发复制GC释放217214(10MB)个AllocSpace对象,0(0B)个LOS对象,56%空闲,8108KB/18MB,暂停112us共129.379ms
- 如果我等待更多,我会不断收到上述几条消息,如果我触摸屏幕,则没有任何交互,整个应用程序似乎冻结。此外,设备的“主页”和“返回”按钮不执行任何操作。如果我在尝试再次最大化应用程序时最小化应用程序,则会出现很大的延迟,并且当应用程序最终打开时,一切都没有响应(按钮不执行任何操作,您甚至无法滚动)。所以,我被迫杀死该应用程序。
观察和注意事项:
上述步骤中描述的问题并不总是发生。但是,当我尝试重现它时,它发生在应用程序运行时间的大约一半。
我在重现问题时使用分析器运行了我的应用程序,并且在上述所有步骤中,内存消耗从开始到结束都保持在同一水平。
请记住,我已经在只有 3GB RAM 的小米 Mi A2 Lite 设备中看到并重现了这个问题。我没有尝试在任何其他设备上重现它。
出现此问题的 Activity 包含一些带有许多图像的视图。当我不使用任何图像填充 Activity 布局中的某些视图时,上述日志消息会报告更多可用内存百分比。该问题有时仍会出现,但您必须让手机闲置更长的时间才能使应用程序冻结。此外,图像的尺寸越大,这个问题就越容易被重现。
我的结论:
我观察到,当我收到上述日志消息时,可用内存百分比逐渐降低,并且应用程序在达到低于 60% 的值时开始冻结。因此,我假设设备的内存无法处理那么多数据,这就是垃圾收集器不断重新分配内存以进行优化的原因。当然,最简单的解决方案是拥有更多内存的设备或使用更少和更小尺寸的图像,但我更喜欢更强大的解决方案。
问题:
我想知道其他人是否在他们的应用程序中观察到了同样的行为,以及他们是如何处理的。
一开始,我收到以“Background concurrent copying GC freed”开头的日志消息(参见步骤 3),在一堆消息之后,我收到了几条消息(参见步骤 4),其中第一条消息以“Background concurrent copying GC”开头freed”,第二条消息以“Background young concurrent copying GC freed”开头。那个“年轻并发”是否意味着任何不同,还是我应该忽略这个变化?
有没有其他工具可以帮助我进一步调查这个问题?
解决方案
我解决了这个问题,原来我的一位同事创建了一个新线程,即使在空闲时也能保持活动状态。结果出现了“Background young concurrent copying GC freed”消息,设备逐渐开始内存不足。因此,对于观察到相同消息或行为的任何人,我建议他们分析检查应用程序的内存消耗,尤其是多线程功能。
推荐阅读
- algorithm - 用于为密码破解者提取列表子集的组合算法
- java - 如何正确编写“重定向”(Spring MVC + Security)
- sql - 在 SSRS 报告中过滤多维 OLAP 多维数据集,使用存储过程检索参数值
- c# - 无法使用位图下载图像
- scikit-learn - 文本分类:原始字典输入和文本向量化
- firebase - 如果在 2019 年 10 月之后无法使用旧数据,那么在 Google Analytics 中链接到 Firebase 项目有什么优势?
- python-3.x - 将csv列中的一行拆分为多行,在python中保持其他列相同
- neo4j - 如何通过计算一阶和二阶关注者的数量来过滤 Twitter 用户?
- vb.net - 根据屏幕大小自动调整大小的控件
- powershell - PowerShell(或 CMD)中具有相对文件路径的 md5 哈希