jvm Linux OOM-Killer和G1 GC内存消耗

qij5mzcb  于 10个月前  发布在  Linux
关注(0)|答案(1)|浏览(85)

我有一个Java应用程序在Liberica JDK 8(HotSpot VM,G1 GC)上运行,该应用程序位于一台具有24 GB RAM的Oracle Linux计算机上。应用程序的最大堆大小为-Xmx15g,它的利用率很高(由于其负载配置文件),并且是服务器上唯一具有此类需求的进程。
有时(通常在几十个小时的正常运行时间后),应用程序会被Linux的oom-killer杀死。为了找到根本原因,我在详细模式下启用了JVM Native Memory Tracking(NMT),在预热后不久建立了基准,并收集了34个正常运行时间小时(正好在进程再次被终止之前)的以下统计信息:x1c 0d1x的数据
根据Oracle的NMT内存类别文档,我预计最重的Internal类别将填充Direct ByteBuffers之类的内容。但是,NMT详细信息显示,在这3 GB的Internal中,**几乎70%**都是由如下分配组成的:

[0x00007faeb7f9b5b5] BitMap::BitMap(unsigned long, bool)+0x1d5
[0x00007faeb82ca08f] OtherRegionsTable::add_reference(void*, int)+0x57f
[0x00007faeb82e0f40] InstanceKlass::oop_oop_iterate_nv(oopDesc*, FilterOutOfRegionClosure*)+0xc0
[0x00007faeb82c3373] HeapRegion::oops_on_card_seq_iterate_careful(MemRegion, FilterOutOfRegionClosure*, signed char*)+0x163
                             (malloc=1154790KB type=Internal +846638KB #577395 +423319)

字符串
总共有8个这样的块,其中oops_on_card_seq_iterate_careful(…)方法调用在下一个堆栈帧上具有各种类,例如:

  • InstanceRefKlass
  • InstanceKlass
  • ObjArrayKlass

根据这些标识符,我发现这些例程是G1 GC的一部分。但是,我无法从corresponding JVM options中可用的G1参数中找到影响它们行为(内存消耗)的方法。
查看此相关的SO answer,我已尝试将-XX:G1HeapRegionSize从其符合人体工程学的计算4 MB增加到手动设置8 MB,但没有观察到显著变化。
所以问题是:
1.为什么纯G1相关活动被NMT记录到内部类别中?(非GC)
1.有没有办法让G1消耗更少的本机内存?(希望将其更改为其他GC,在此情况下不提供此选项)

evrscar2

evrscar21#

为什么NMT将纯G1相关活动记录到内部类别中?(非GC)
NMT不知道其为G1相关活性:它并不遍历堆栈来找出分配类型,它只是使用传递给分配函数的类型。
正如您在堆栈跟踪中所看到的,分配发生在BitMap构造函数中。这是一个在许多地方使用的通用类,而不仅仅是GC。BitMap类具有与mtInternal类型关联的分配器:

ArrayAllocator<bm_word_t, mtInternal> _map_allocator;

字符串
在较新的JDK版本中,BitMap具有从外部传递的变量分配类型。
有没有办法让G1消耗更少的本机内存?
迁移到JDK 17或更高版本。G1 GC获得了 * 吨 * 的改进,这些改进永远不会被后移植到JDK 8。在JDK 8中调优GC对于性能顾问来说是一座金矿,但如果您关心时间和资源-升级JDK是最好的投资。

相关问题