为什么在使用 G1 收集器时 -XX:+ExplicitGCInvokesConcurrent 不是默认值?
Why isn't -XX:+ExplicitGCInvokesConcurrent the default when using the G1 collector?
在内存数据库的上下文中,我们将堆外内存与热点的 G1 收集器结合使用。
但是,当堆外内存使用量达到 MaxDirectMemorySize 时,JDK 代码使用 System.gc()
触发了 full GC。这导致了一个漫长而痛苦的世界 GC 停止,这似乎也将所有当前的 live set 放在了旧的 gen 中,绕过了幸存者(从而增加了裙带关系问题)。设置 -XX:+ExplicitGCInvokesConcurrent
时不会发生这种情况:GC 速度更快并且尊重幸存者。
既然 System.gc()
是 JDK 内部使用的东西,为什么这个选项在热点中没有默认打开?这个标志是否会引发理论或实践问题?还是仅仅是出于兼容性原因?是否有人有在生产环境中使用此选项的经验,并遇到过问题?
看来,JDK 的人也还没有回答这个问题(请参阅 Charlie Hunt 在 JDK-8071770 上的评论)。
到目前为止,我发现使用此选项的唯一缺点是默认情况下并发 GC 不会卸载 类(请参阅 JDK-6541037)。但如果这是您的问题,您可以改用 -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses。
2017 年编辑:
已为 jdk10 打开具有相同问题的特定工单:JDK-8160392
在内存数据库的上下文中,我们将堆外内存与热点的 G1 收集器结合使用。
但是,当堆外内存使用量达到 MaxDirectMemorySize 时,JDK 代码使用 System.gc()
触发了 full GC。这导致了一个漫长而痛苦的世界 GC 停止,这似乎也将所有当前的 live set 放在了旧的 gen 中,绕过了幸存者(从而增加了裙带关系问题)。设置 -XX:+ExplicitGCInvokesConcurrent
时不会发生这种情况:GC 速度更快并且尊重幸存者。
既然 System.gc()
是 JDK 内部使用的东西,为什么这个选项在热点中没有默认打开?这个标志是否会引发理论或实践问题?还是仅仅是出于兼容性原因?是否有人有在生产环境中使用此选项的经验,并遇到过问题?
看来,JDK 的人也还没有回答这个问题(请参阅 Charlie Hunt 在 JDK-8071770 上的评论)。
到目前为止,我发现使用此选项的唯一缺点是默认情况下并发 GC 不会卸载 类(请参阅 JDK-6541037)。但如果这是您的问题,您可以改用 -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses。
2017 年编辑: 已为 jdk10 打开具有相同问题的特定工单:JDK-8160392