实用分享JVM和Docker默认设置中的陷阱

1,266 阅读2分钟

以下是JVM中Docker默认设置之间的一些常见陷阱。

首先,有很多关于JVM和容器意识的文章:

在本文中,我使用Java 11,这意味着垃圾收集器的默认值应该是G1GC! 让我们看一下默认值,JVM会根据内存大小和提供的CPU自动选择这些默认值。

基于Docker CPU的默认GC

$ docker run --cpus="2" openjdk:11-jre java -XX:+PrintFlagsFinal -version | grep -E "(MAX|UseSerialGC|UseG1GC|MaxHeapSize)"size_t MaxHeapSize = 5200936960 {product} {ergonomic}bool UseG1GC = true {product} {ergonomic}bool UseSerialGC = false {product} {default}$ docker run --cpus="1" openjdk:11-jre java -XX:+PrintFlagsFinal -version | grep -E "(MAX|UseSerialGC|UseG1GC|MaxHeapSize)"size_t MaxHeapSize = 5200936960 {product} {ergonomic}bool UseG1GC = false {product} {default}bool UseSerialGC = true {product} {ergonomic}

注意你的Docker容器中的CPU数量; 垃圾收集器的类型可以完全不同。

基于Docker内存的默认GC

$ docker run -m 2g openjdk:11-jre java -XX:+PrintFlagsFinal -version | grep -E "(MAX|UseSerialGC|UseG1GC|MaxHeapSize)"size_t MaxHeapSize = 536870912 {product} {ergonomic}bool UseG1GC = true {product} {ergonomic}bool UseSerialGC = false {product} {default}$ docker run -m 1g openjdk:11-jre java -XX:+PrintFlagsFinal -version | grep -E "(MAX|UseSerialGC|UseG1GC|MaxHeapSize)"size_t MaxHeapSize = 268435456 {product} {ergonomic}bool UseG1GC = false {product} {default}bool UseSerialGC = true {product} {ergonomic}

在上面的代码片段中,JVM根据提供的内存大小自动更改了默认垃圾回收器。

默认堆大小始终是可用内存的1/4!

$ docker run -m 512m openjdk:11-jre java -XX:+PrintFlagsFinal -version | grep -E "(MAX|UseSerialGC|UseG1GC|MaxHeapSize)"size_t MaxHeapSize = 134217728 {product} {ergonomic}bool UseG1GC = false {product} {default}bool UseSerialGC = true {product} {ergonomic}$ docker run -m 256m openjdk:11-jre java -XX:+PrintFlagsFinal -version | grep -E "(MAX|UseSerialGC|UseG1GC|MaxHeapSize)"size_t MaxHeapSize = 132120576 {product} {ergonomic}bool UseG1GC = false {product} {default}bool UseSerialGC = true {product} {ergonomic}

JVM从一定数量的内存中停止选择堆大小的1/4,并开始使比率越来越小,以为你的应用程序提供更大的堆内存。

为什么选择SerialGC?

$ docker run -m 1g openjdk:11-jre java -XX:+PrintFlagsFinal -version | grep -E "(MAX|UseSerialGC|UseG1GC|MaxHeapSize)"size_t MaxHeapSize = 268435456 {product} {ergonomic}bool UseG1GC = false {product} {default}bool UseSerialGC = true {product} {ergonomic}$ docker run -m 1g openjdk:11-jre java -Xmx700m -XX:+PrintFlagsFinal -version | grep -E "(MAX|UseSerialGC|UseG1GC|MaxHeapSize)"size_t MaxHeapSize = 734003200 {product} {command line}bool UseG1GC = false {product} {default}bool UseSerialGC = true {product} {ergonomic}

这很奇怪,根据上面的示例,我们仍然应该将G1GC作为默认值,但是知道我们可以注意JVM选择了SerialGC。 一讲,你总是必须尝试一下JVM选择了哪些默认值,并考虑它是否合理并适合你。你会注意到JVM定义的参数被标记为符合人体工程学的JVM选项。

感谢你阅读我的文章,感兴趣的欢迎点赞关注。

如有不足之处,欢迎评论交流。

抽丝剥茧,细说架构那些事~