一個效能較好的JVM引數配置

Hi_峰兄發表於2015-07-28

一個效能較好的web伺服器jvm引數配置:

-server	//伺服器模式
-Xmx2g //JVM最大允許分配的堆記憶體,按需分配
-Xms2g //JVM初始分配的堆記憶體,一般和Xmx配置成一樣以避免每次gc後JVM重新分配記憶體。
-Xmn256m //年輕代記憶體大小,整個JVM記憶體=年輕代 + 年老代 + 持久代
-XX:PermSize=128m //持久代記憶體大小
-Xss256k //設定每個執行緒的堆疊大小
-XX:+DisableExplicitGC //忽略手動呼叫GC, System.gc()的呼叫就會變成一個空呼叫,完全不觸發GC
-XX:+UseConcMarkSweepGC //併發標記清除(CMS)收集器
-XX:+CMSParallelRemarkEnabled //降低標記停頓
-XX:+UseCMSCompactAtFullCollection //在FULL GC的時候對年老代的壓縮
-XX:LargePageSizeInBytes=128m //記憶體頁的大小
-XX:+UseFastAccessorMethods //原始型別的快速優化
-XX:+UseCMSInitiatingOccupancyOnly //使用手動定義初始化定義開始CMS收集
-XX:CMSInitiatingOccupancyFraction=70 //使用cms作為垃圾回收使用70%後開始CMS收集

說明:

-Xmn和-Xmx之比大概是1:9,如果把新生代記憶體設定得太大會導致young gc時間較長

一個好的Web系統應該是每次http請求申請記憶體都能在young gc回收掉,full gc永不發生,當然這是最理想的情況

xmn的值應該是保證夠用(夠http併發請求之用)的前提下設定得儘量小

web伺服器和遊戲伺服器的配置思路不太一樣,最重要的區別是對遊戲伺服器的xmn即年輕代設定比較大,和Xmx大概1:3的關係,因為遊戲伺服器一般是長連線,在保持一定的併發量後需要較大的年輕代堆記憶體,如果設定得大小了會經常引發young gc

對JVM的簡介

一個效能較好的jvm引數配置以及jvm的簡介

由上圖可以看出JVM堆記憶體的分類情況,JVM記憶體被分成多個獨立的部分。

廣泛地說,JVM堆記憶體被分為兩部分——年輕代(Young Generation)和老年代(Old Generation)。

年輕代

年輕代是所有新物件產生的地方。當年輕代記憶體空間被用完時,就會觸發垃圾回收。這個垃圾回收叫做Minor GC。年輕代被分為3個部分——Enden區和兩個Survivor區。

年輕代空間的要點:

大多數新建的物件都位於Eden區。

當Eden區被物件填滿時,就會執行Minor GC。並把所有存活下來的物件轉移到其中一個survivor區。

Minor GC同樣會檢查存活下來的物件,並把它們轉移到另一個survivor區。這樣在一段時間內,總會有一個空的survivor區。

經過多次GC週期後,仍然存活下來的物件會被轉移到年老代記憶體空間。通常這是在年輕代有資格提升到年老代前通過設定年齡閾值來完成的。

年老代

年老代記憶體裡包含了長期存活的物件和經過多次Minor GC後依然存活下來的物件。通常會在老年代記憶體被佔滿時進行垃圾回收。老年代的垃圾收集叫做Major GC。Major GC會花費更多的時間。

Stop the World事件

所有的垃圾收集都是“Stop the World”事件,因為所有的應用執行緒都會停下來直到操作完成(所以叫“Stop the World”)。

因為年輕代裡的物件都是一些臨時(short-lived )物件,執行Minor GC非常快,所以應用不會受到(“Stop the World”)影響。

由於Major GC會檢查所有存活的物件,因此會花費更長的時間。應該儘量減少Major GC。因為Major GC會在垃圾回收期間讓你的應用反應遲鈍,所以如果你有一個需要快速響應的應用發生多次Major GC,你會看到超時錯誤。

垃圾回收時間取決於垃圾回收策略。這就是為什麼有必要去監控垃圾收集和對垃圾收集進行調優。從而避免要求快速響應的應用出現超時錯誤。

永久代

永久代或者“Perm Gen”包含了JVM需要的應用後設資料,這些後設資料描述了在應用裡使用的類和方法。注意,永久代不是Java堆記憶體的一部分。

永久代存放JVM執行時使用的類。永久代同樣包含了Java SE庫的類和方法。永久代的物件在full GC時進行垃圾收集。

方法區

方法區是永久代空間的一部分,並用來儲存型別資訊(執行時常量和靜態變數)和方法程式碼和建構函式程式碼。

記憶體池

如果JVM實現支援,JVM記憶體管理會為建立記憶體池,用來為不變物件建立物件池。字串池就是記憶體池型別的一個很好的例子。記憶體池可以屬於堆或者永久代,這取決於JVM記憶體管理的實現。

執行時常量池

執行時常量池是每個類常量池的執行時代表。它包含了類的執行時常量和靜態方法。執行時常量池是方法區的一部分。

Java棧記憶體

Java棧記憶體用於執行執行緒。它們包含了方法裡的臨時資料、堆裡其它物件引用的特定資料。

Java垃圾回收

Java垃圾回收會找出沒用的物件,把它從記憶體中移除並釋放出記憶體給以後建立的物件使用。Java程式語言中的一個最大優點是自動垃圾回收,不像其他的程式語言那樣需要手動分配和釋放記憶體,比如C語言。

垃圾收集器是一個後臺執行程式。它管理著記憶體中的所有物件並找出沒被引用的物件。所有的這些未引用的物件都會被刪除,回收它們的空間並分配給其他物件。

一個基本的垃圾回收過程涉及三個步驟:

標記:這是第一步。在這一步,垃圾收集器會找出哪些物件正在使用和哪些物件不在使用。

正常清除:垃圾收集器清會除不在使用的物件,回收它們的空間分配給其他物件。

壓縮清除:為了提升效能,壓縮清除會在刪除沒用的物件後,把所有存活的物件移到一起。這樣可以提高分配新物件的效率。

簡單標記和清除方法存在兩個問題:

效率很低。因為大多數新建物件都會成為“沒用物件”。

經過多次垃圾回收週期的物件很有可能在以後的週期也會存活下來。

上面簡單清除方法的問題在於Java垃圾收集的分代回收的,而且在堆記憶體裡有年輕代和年老代兩個區域。

Java垃圾回收型別

這裡有五種可以在應用裡使用的垃圾回收型別。

僅需要使用JVM開關就可以在我們的應用裡啟用垃圾回收策略。

Serial GC(-XX:+UseSerialGC):Serial GC使用簡單的標記、清除、壓縮方法對年輕代和年老代進行垃圾回收,即Minor GC和Major GC。Serial GC在client模式(客戶端模式)很有用,比如在簡單的獨立應用和CPU配置較低的機器。這個模式對佔有記憶體較少的應用很管用。

Parallel GC(-XX:+UseParallelGC):除了會產生N個執行緒來進行年輕代的垃圾收集外,Parallel GC和Serial GC幾乎一樣。這裡的N是系統CPU的核數。我們可以使用 -XX:ParallelGCThreads=n 這個JVM選項來控制執行緒數量。並行垃圾收集器也叫throughput收集器。因為它使用了多CPU加快垃圾回收效能。Parallel GC在進行年老代垃圾收集時使用單執行緒。

Parallel Old GC(-XX:+UseParallelOldGC):和Parallel GC一樣。不同之處,Parallel Old GC在年輕代垃圾收集和年老代垃圾回收時都使用多執行緒收集。

併發標記清除(CMS)收集器(-XX:+UseConcMarkSweepGC):CMS收集器也被稱為短暫停頓併發收集器。它是對年老代進行垃圾收集 的。CMS收集器通過多執行緒併發進行垃圾回收,儘量減少垃圾收集造成的停頓。CMS收集器對年輕代進行垃圾回收使用的演算法和Parallel收集器一樣。 這個垃圾收集器適用於不能忍受長時間停頓要求快速響應的應用。可使用 -XX:ParallelCMSThreads=n JVM選項來限制CMS收集器的執行緒數量。

G1垃圾收集器(-XX:+UseG1GC) G1(Garbage First):垃圾收集器是在Java 7後才可以使用的特性,它的長遠目標時代替CMS收集器。G1收集器是一個並行的、併發的和增量式壓縮短暫停頓的垃圾收集器。G1收集器和其他的收集器運 行方式不一樣,不區分年輕代和年老代空間。它把堆空間劃分為多個大小相等的區域。當進行垃圾收集時,它會優先收集存活物件較少的區域,因此叫 “Garbage First”。

相關文章