一個性能較好的webserverjvm參數配置:
-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並發請求之用)的前提下設置得盡量小
webserver和游戲server的配置思路不太一樣。最重要的差別是對游戲server的xmn即年輕代設置比較大。和Xmx大概1:3的關系,由於游戲server通常是長連接,在保持一定的並發量后須要較大的年輕代堆內存。假設設置得大小了會常常引發young gc
- 對JVM的簡單介紹

由上圖能夠看出jvm堆內存的分類情況,JVM內存被分成多個獨立的部分。
廣泛地說。JVM堆內存被分為兩部分——年輕代(Young Generation)和老年代(Old Generation)。
- 年輕代
當年輕代內存空間被用完時,就會觸發垃圾回收。
這個垃圾回收叫做Minor GC。年輕代被分為3個部分——Enden區和兩個Survivor區。
年輕代空間的要點:
大多數新建的對象都位於Eden區。
當Eden區被對象填滿時,就會運行Minor GC。並把全部存活下來的對象轉移到當中一個survivor區。
Minor GC相同會檢查存活下來的對象。並把它們轉移到還有一個survivor區。
這樣在一段時間內,總會有一個空的survivor區。
經過多次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,你會看到超時錯誤。
垃圾回收時間取決於垃圾回收策略。這就是為什么有必要去監控垃圾收集和對垃圾收集進行調優。
從而避免要求高速響應的應用出現超時錯誤。
- 永久代
永久代存放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”。
