JVM的參數有不少不少,根據個人統計JDK8中JVM的參數總共有1853個,正式的參數也有680個。html
這麼多參數帶給咱們的是對JVM的細粒度的控制,可是並非全部的參數都須要咱們本身去調節的,咱們須要關注的是一些最經常使用的,對性能影響比較大的GC參數便可。java
爲了更好的讓你們理解JDK8中 GC的調優的祕籍,這裏特地準備了八張圖。在本文的最後,還附帶了一個總結的PDF all in one文檔,你們把PDF下載回去,遇到問題就看兩眼,不美嗎?算法
爲了更好的提高GC的效率,現代的JVM都是採用的分代垃圾回收的策略(ZGC不是)。多線程
java運行時內存能夠分爲JVM內存和非JVM內存。併發
JVM內存又能夠分爲堆內存和非堆內存。app
堆內存你們都很熟悉了,YoungGen中的Eden,Survivor和OldGen。ide
非堆內存中存儲的有thread Stack,Code Cache, NIO Direct Buffers,Metaspace等。性能
注意這裏的Metaspace元空間是方法區在JDK8的實現,它是在本地內存中分配的。spa
JDK8中到底有哪些可使用的GC呢?.net
這裏咱們以HotSpot JVM爲例,總共可使用4大GC方式:
其中對於ParallelGC和CMS GC又能夠對年輕代和老年代分別設置GC方式。
你們看到上圖可能有一個疑問,Parallel scavenge和Parallel有什麼區別呢?
其實這兩個GC的算法是相似的,Parallel Scavenge收集器也常常稱爲「吞吐量優先」收集器,Parallel Scavenge收集器提供了兩個參數用於精確控制吞吐量; -XX:MaxGCPauseMillis:控制最大垃圾收集停頓時間; -XX:GCTimeRatio:設置吞吐量大小。
同時Parallel Scavenge收集器可以配合自適應調節策略,把內存管理的調優任務交給虛擬機去完成。
JDK8中默認開啓的是ParallelGC。
若是想研究和理解GC的內部信息,GC信息打印是少不了的:
上圖提供了一些很是有用的GC日誌的控制參數。
JVM分爲Heap區和非Heap區,各個區又有更細的劃分,下面就是調整各個區域大小的參數:
TLAB你們還記得嗎?
若是一個對象的分配是在方法內部,而且沒有多線程訪問的狀況下,那麼這個對象其實能夠看作是一個本地對象,這樣的對象無論建立在哪裏都只對本線程中的本方法可見,所以能夠直接分配在棧空間中。
棧上分配的對象由於不用考慮同步,因此執行速度確定會更加快速,這也是爲何JVM會引入棧上分配的緣由。
上圖就是TLAB的參數。
雖然JDK8的GC這麼多,可是他們有一些通用的GC參數:
這裏講解一下Young space tenuring,怎麼翻譯我不是很清楚,這個主要就是指Young space中的對象通過多少次GC以後會被提高到Old space中。
CMS全稱是Concurrent mark sweep。是一個很是很是複雜的GC。
複雜到什麼程度呢?光光是CMS調優的參數都有一百多個!
下圖是經常使用的CMS的參數。
CMS這裏就很少講了,由於在JDK9以後,CMS就已經被廢棄了。鄭州那家不孕不育好:http://byby.zztjyy.com/
主要緣由是CMS太過複雜,若是要向下兼容須要巨大的工做量,而後就直接被廢棄了。
在JDK9以後,默認的GC是G1。
G1收集器是分代的和region化的,也就是整個堆內存被分爲一系列大小相等的region。在啓動時,JVM設置region的大小,根據堆大小的不一樣,region的大小能夠在1MB到32MB之間變更,region的數量最多不超過2048個。Eden區、Survivor區、老年代是這些region的邏輯集合,它們並非連續的。
G1中的垃圾收集過程:年輕代收集和混合收集交替進行,背後有全局的併發標記週期在進行。當老年代分區佔用的空間達到或超過初始閾值,就會觸發併發標記週期。
下圖是G1的調優參數:
上面總共8副圖,我把他們作成了一個PDF,預覽界面大概是這樣子的:
鄭州同濟不孕不育醫院:http://yyk.39.net/zz3/zonghe/fc964.html