java - JVM老年代不断增加,而eden和survivor不变

标签 java memory garbage-collection heap-memory

我有一个 java spring boot 应用程序,该应用程序应该长时间运行,并且整个过程中需要响应时间 < 50 毫秒。通常情况下,我们能够提供此服务,但当旧一代接近填满时,CMS 就会启动,我们的响应时间就会违反 SLA。我可以使用什么策略来确保完全 GC 永远不会启动。

我的服务器是 IO 密集型服务器,我们不在内存中存储任何内容,但有大量并发 IO(30k rpm),每个 IO 响应携带大约 3-4MB 的数据。从日志中我观察到minor GC在一秒内运行了近3-4次,由于eden和survivor空间较小(Eden空间为600MB,survivor空间为75MB),minor GC被非常频繁地触发。由于 GC 非常频繁,对象可能会在阈值次要 GC(15) 中幸存下来,并升级到旧代。因此,我通过设置 -XX:NewRatio=1 来增加我的年轻一代空间。

问题仍然存在,我可以在一秒内看到分配失败日志(如下)3-4次

[GC(分配失败)56455.997:[ParNew:10705358K->222390K(11796480K),0.0467254 秒] 13148872K->2667031K(24903680K),0.0468292 秒] [次:用户=0.34 系统=0.00,真实=0.05秒]

使用新的遗迹我监控了内存,年轻一代是恒定的,而老一代不断增加,下面是快照。

enter image description here

我认为对于我的应用程序来说,一个好的堆分配策略是年轻一代不断被填充和清空,而老一代几乎不被使用,因为我们几乎没有任何长期存在的对象。请建议如何实现上述目标,或者您可能想到的任何更好的策略

最佳答案

以下是建议:

  1. 大型物体,例如数组等是在旧一代空间中创建的。因此,请检查您正在创建哪些大型对象以及它们停留了多长时间。

  2. 当对象达到保有阈值时,对象将移至旧 GC。因此,你可以朝这个方向看。

  3. 检查次要 GC 和主要 GC 的执行情况,就好像这些 GC 快速填充或达到对象移动到旧代时的阈值一样。

  4. 查看伊甸园和幸存者的大小,如果它们太小,可能会触发主要GC并导致对象移动到旧代。

关于java - JVM老年代不断增加,而eden和survivor不变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58692231/

相关文章:

java - 在安卓上打开文件

c++ - 内存泄漏,窗口是否有防止达到最大内存的保护措施?

memory - Appfog 实例与内存

Python:记录垃圾收集器

java - 如何让 Byte Buddy 将多种类型加载到同一个包装类加载器中

java - 智能 : Fatal error compiling: invalid target release: 1. 8

php - Codeigniter 优化/加载模型的最佳位置是?

java - 如何删除特定对象?

java - 详细的 Java GC 日志

java - 按键事件未触发