我们的应用程序面临一个奇怪的内存泄漏问题。
GC 配置:ParNew + CMS
某些类型的对象过早升级为老年代并导致严重的碎片问题。
- 幸存者有足够的空间容纳这些物品
- 老化阈值为 15 个周期,并没有基于此发生过早升级。
关于这些对象:这些是使用 Java 辅助库创建的代理对象。
由于对此类对象进行了不必要的提升,老年代很快就被污染了,并且正在发生严重的碎片化。
我们的观察:
- 对象仅在伊甸园中分配。没有尺寸相关的问题。
- 对象的作用域非常小,可以在下一次次要 gc 中进行 GC。
- 为了确保这一点,我们在finalize()中打印了一些记录器,并观察到范围在请求后立即结束。就在第一次次要 GC 之后。
注意: finalize() 只是为了跟踪目的而添加的。即使没有 finalize() 旧代促销也会发生。
- 在一次次要 gc 之后:
- 期望是该对象将被清除。
- 但是该对象正在升级为老年代。在多个堆转储的帮助下,我们能够跟踪对象升级到老年代。
- 所有这些对象都在老一代中积累,并由老一代 GC 进行 GC。
- 此行为仅在生产服务器中可见,在测试环境中不可重现。
请建议如何进一步进行并解决此问题。
另一个有趣的更新:使用 G1GC,当使用 G1GC 时,对象会被正确清除。使用 finalize() 方法检查,在第一个循环之后,对象变得无法访问。在下一个小循环之后,对象不在那里。对于 G1GC,问题不存在。