以下是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乾貨