以下是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选项。

> 喜欢这篇文章的可以点个赞,欢迎大家留言评论,记得关注我,每天持续更新技术干货、职场趣事、海量面试资料等等

 > 如果你对java技术很感兴趣也可以交流学习,共同学习进步。 

> 不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代


文章写道这里,欢迎完善交流。最后奉上近期整理出来的一套完整的java架构思维导图,分享给大家对照知识点参考学习。有更多JVM、Mysql、Tomcat、Spring Boot、Spring Cloud、Zookeeper、Kafka、RabbitMQ、RockerMQ、Redis、ELK、Git等Java干货