G1 GC相关内存被NMT标记为Internal类及内存优化技术问询
G1 GC 本地内存占用与NMT分类问题解答
1. 为何G1 GC相关内存被归类到NMT的Internal类别而非GC类别?
NMT的内存分类并非依据内存的功能用途,而是看内存分配时的调用标记。在JDK 8的G1实现中,BitMap、OtherRegionsTable这类底层结构的内存分配,走的是通用内部内存分配路径,没有被专门标记为GC类别。也就是说,只要分配代码没有显式打上GC类别的标记,哪怕内存是为GC服务的,也会被归到Internal类别下。
2. 不更换GC的前提下降低G1本地内存占用的方法
针对你遇到的由G1 Region引用跟踪逻辑导致的Internal内存增长,可尝试以下调整:
- 限制并发细化线程数:设置
-XX:G1ConcRefinementThreads为小于CPU核心数的值(比如核心数的1/2),减少线程本地维护的BitMap等结构的内存开销。 - 优化RSet更新策略:调整
-XX:G1RSetUpdatingPauseTimePercent降低RSet更新在GC停顿中的时间占比,减少临时内存分配;同时设置-XX:G1RSetRegionEntries指定RSet初始条目数,避免动态扩容带来的内存浪费。 - 固定并发标记触发阈值:启用
-XX:+UnlockExperimentalVMOptions -XX:G1UseAdaptiveIHOP=false,手动设置-XX:InitiatingHeapOccupancyPercent(比如设为70),避免频繁触发并发标记导致的内存波动。 - 减少堆碎片化:因为你的应用堆使用率极高,长期运行易产生大量碎片,导致G1需要维护更多Region的引用信息。设置
-XX:G1HeapWastePercent为更低的值(比如5),让G1更积极地清理碎片,减少需要跟踪的Region数量。 - 升级JDK 8补丁版本:Oracle在JDK 8u200及以后的补丁中,优化了G1的BitMap和RSet内存管理,修复了部分内存泄漏问题,升级到最新的JDK 8补丁版可能直接缓解该问题。
调整后建议持续监控NMT的Internal类别内存变化,验证优化效果。
内容的提问来源于stack exchange,提问作者Toparvion
相关产品推荐
相关产品推荐

