【问题标题】:JVM old geneation keeps increasing while eden and survior are constantJVM老年代不断增加,而eden和survivor不变
【发布时间】:2020-02-29 16:46:26
【问题描述】:

我有一个 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,对象可能会在阈值次要 GCs(15) 中幸存下来,并被提升为老一代。所以我通过制作-XX:NewRatio=1 增加了我的年轻一代空间。

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

[GC (Allocation Failure) 56455.997: [ParNew: 10705358K->222390K(11796480K), 0.0467254 secs] 13148872K->2667031K(24903680K), 0.0468292 secs] [Times: user=0.34 sys=0.00, real=0.05 secs]

使用new relic我监控内存,young gen保持不变,old gen不断增加,下面是snapshot。

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

【问题讨论】:

  • 你找到解决方案了吗?

标签: java memory garbage-collection heap-memory


【解决方案1】:

以下是建议:

  1. 大型对象,例如数组等被创建在旧代空间。因此,请检查您正在创建哪些大型对象以及它们会保留多长时间。

  2. 当满足对象的终身阈值时,对象将移至旧 GC。因此,您可以朝这个方向看。

  3. 检查您的次要 GC 和主要 GC 是如何执行的,就好像它们正在快速填充或满足将对象移至旧代时的阈值。

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

【讨论】:

    猜你喜欢
    • 2020-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 2019-10-29
    • 1970-01-01
    • 1970-01-01
    • 2015-04-25
    相关资源
    最近更新 更多