我们正在将java 8应用程序迁移到java 17,并将GC从G1GC
切换到ZGC
。我们的应用程序作为容器运行,这两个基本映像之间的唯一区别是java的版本。例如,对于java 17版本:
FROM ubuntu:20.04
...
ENV JAVA_HOME /usr/lib/jvm/jdk-17.0.5
ENV PATH $JAVA_HOME/bin:$PATH
及其相关的java选项:
-Xmx100g
-XX:+UseZGC
运行应用程序时,会出现以下gc警告:
[0.018s][warning][gc] ***** WARNING! INCORRECT SYSTEM CONFIGURATION DETECTED! *****
[0.018s][warning][gc] The system limit on number of memory mappings per process might be too low for the given
[0.018s][warning][gc] max Java heap size (102400M). Please adjust /proc/sys/vm/max_map_count to allow for at
[0.018s][warning][gc] least 184320 mappings (current limit is 65530). Continuing execution with the current
[0.018s][warning][gc] limit could lead to a premature OutOfMemoryError being thrown, due to failure to map memory.
几个小时后,在内存达到大约~60GB
之后,应用程序崩溃了:
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(...) failed; error='Not enough space' (errno=12)
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(...) failed; error='Not enough space' (errno=12)
# fatal error: Failed to map memory (Not enough space)
# A fatal error has been detected by the Java Runtime Environment:
[error occurred during error reporting (), id 0xb, SIGSEGV (0xb) at pc=0x00007fc929746941]
我知道调整vm.max_map_count
很可能会解决这个问题,但我的问题是java或GC中到底发生了什么变化,导致了这些警告和最终的错误?
1条答案
按热度按时间dbf7pr2w1#
但我的问题是,Java或GC中究竟发生了什么变化,导致了这些警告并最终导致了这些错误?
它只是ZGC垃圾收集器的一个实现细节,它需要对内存Map进行更细粒度的控制,这意味着Map的总量更大。
旧的收集器通常保留巨大的连续空间的地址空间,并且很少在这些范围中打孔以将内存释放回操作系统。ZGC处理大小不等的非连续范围,这意味着它必须从操作系统请求更多的单独Map。