JVM的結構問題:JVM分兩塊:PermanentSapce和HeapSpace,html
HeapSpace = 【old + new{=Eden,from,to}】java
PermantSpace主要負責存放加載Class類級別的class自己,method,field等反射對象,通常不用配置,JVM的Heap區能夠經過-X參數來設定。linux
當一個URL被訪問時,內存申請以下:程序員
A. JVM會試圖爲相關Java對象在Eden中初始化一塊內存區域;web
B. 當Eden空間足夠時,內存申請結束。不然到下一步;併發
C. JVM試圖釋放在Eden中全部不活躍的對象(這屬於1或更高級的垃圾回收), 釋放後若Eden空間仍然不足以放入新對象,則試圖將部分Eden中活躍對象放入Survivor區;oracle
D. Survivor區被用來做爲Eden及OLD的中間交換區域,當OLD區空間足夠時,Survivor區的對象會被移到Old區,不然會被保留在Survivor區;app
E. 當OLD區空間不夠時,JVM會在OLD區進行徹底的垃圾收集(0級;框架
F. 徹底垃圾收集後,若Survivor及OLD區仍然沒法存放從Eden複製過來的部分對象,致使JVM沒法在Eden區爲新對象建立內存區域,則出現」out of memory錯誤。jvm
JVM參數介紹和調優建議:
Xms/Xmx:定義NEW+OLD段的總尺寸,ms爲JVM啓動時NEW+OLD的內存大小;mx爲最大可佔用的NEW+OLD內存小。在用戶生產環境上通常將這兩個值設爲相同,以減小運行期間系統在內存申請上所花的開銷;
NewSize/MaxNewSize:定義單獨NEW段的尺寸,NewSize爲JVM啓動時NEW的內存大小;MaxNewSize爲最大可佔用的NEW的內存大小。在用戶生產環境上通常將這兩個值設爲相同,以減小運行期間系統在內存申請上所花的開銷;
Xms/Xmx和NewSize/MaxNewSize定義好後,OLD區間也天然定義完畢了,即OLD區初始大小=(Xms-NewSize),OLD區最大可佔用大小=(Xmx-MaxNewSize);
PermSize/MaxPermSize:定義Perm段的尺寸,PermSize爲JVM啓動時Perm的內存大小;MaxPermSize爲最大可佔用的Perm內存大小。在用戶生產環境上通常將這兩個值設爲相同,以減小運行期間系統在內存申請上所花的開銷;
SurvivorRatio:設置Survivor空間和Eden空間的比例。
以上各值的最大值與初始值的差值爲各區段的virtual區,這部分保留的內存不會被其餘進程使用。
內存溢出的可能性
1. OLD段溢出
這種內存溢出是最多見的狀況之一,產生的緣由多是:
1) 設置的內存參數太小(Xms/Xmx, NewSize/MaxNewSize)
2) 程序問題
單個程序持續進行消耗內存的處理,如循環幾千次的字符串處理,對字符串處理應建議使用StringBuffer。此時不會報內存溢出錯,卻會使系統持續垃圾收集,沒法處理其它請求,相關問題程序可經過Thread Dump獲取(見系統問題診斷一章)單個程序所申請內存過大,有的程序會申請幾十乃至幾百兆內存,此時JVM也會因沒法申請到資源而出現內存溢出,對此首先要找到相關功能,而後交予程序員修改,要找到相關程序,必須在Apache日誌中尋找。當Java對象使用完畢後,其所引用的對象卻沒有銷燬,使得JVM認爲他仍是活躍的對象而不進行回收,這樣累計佔用了大量內存而沒法釋放。因爲目前市面上尚未對系統影響小的內存分析工具,故此時只能和程序員一塊兒定位。
2. Perm段溢出
一般因爲Perm段裝載了大量的Servlet類而致使溢出,目前的解決辦法:
1) 將PermSize擴大,通常256M可以知足要求
2) 若別無選擇,則只能將servlet的路徑加到CLASSPATH中,但通常不建議這麼處理
3. C Heap溢出
系統對C Heap沒有限制,故C Heap發生問題時,Java進程所佔內存會持續增加,直到佔用全部可用系統內存
jvm參數設置
1: heap size
a: -Xmx<n>
指定 jvm 的最大 heap 大小 , 如 :-Xmx=2g
b: -Xms<n>
指定 jvm 的最小 heap 大小 , 如 :-Xms=2g , 高併發應用, 建議和-Xmx同樣, 防止由於內存收縮/忽然增大帶來的性能影響。
c: -Xmn<n>
指定 jvm 中 New Generation 的大小 , 如 :-Xmn256m。 這個參數很影響性能, 若是你的程序須要比較多的臨時內存, 建議設置到512M, 若是用的少, 儘可能下降這個數值, 通常來講128/256足以使用了。
d: -XX:PermSize=<n>
指定 jvm 中 Perm Generation 的最小值 , 如 :-XX:PermSize=32m。 這個參數須要看你的實際狀況,。 能夠經過jmap 命令看看到底須要多少。
e: -XX:MaxPermSize=<n>
指定 Perm Generation 的最大值 , 如 :-XX:MaxPermSize=64m
f: -Xss<n>
指定線程桟大小 , 如 :-Xss128k, 通常來講,webx框架下的應用須要256K。 若是你的程序有大規模的遞歸行爲,請考慮設置到512K/1M。 這個須要全面的測試才能知道。 不過,256K已經很大了。 這個參數對性能的影響比較大的。
g: -XX:NewRatio=<n>
指定 jvm 中 Old Generation heap size 與 New Generation 的比例 , 在使用 CMS GC 的狀況下此參數失效 , 如 :-XX:NewRatio=2
h: -XX:SurvivorRatio=<n>
指 定 New Generation 中 Eden Space 與一個 Survivor Space 的 heap size 比例 ,-XX:SurvivorRatio=8, 那麼在總共 New Generation 爲 10m 的狀況下 ,Eden Space 爲 8m
i: -XX:MinHeapFreeRatio=<n>
指定 jvm heap 在使用率小於 n 的狀況下 ,heap 進行收縮 ,Xmx==Xms 的狀況下無效 , 如 :-XX:MinHeapFreeRatio=30
j: -XX:MaxHeapFreeRatio=<n>
指定 jvm heap 在使用率大於 n 的狀況下 ,heap 進行擴張 ,Xmx==Xms 的狀況下無效 , 如 :-XX:MaxHeapFreeRatio=70
k: -XX:LargePageSizeInBytes=<n>
指定 Java heap 的分頁頁面大小 , 如 :-XX:LargePageSizeInBytes=128m
2: garbage collector
a: -XX:+UseParallelGC
指 定在 New Generation 使用 parallel collector, 並行收集 , 暫停 app threads, 同時啓動多個垃圾回收 thread, 不能和 CMS gc 一塊兒使用 . 系統噸吐量優先 , 可是會有較長長時間的 app pause, 後臺系統任務可使用此 gc
b: -XX:ParallelGCThreads=<n>
指定 parallel collection 時啓動的 thread 個數 , 默認是物理 processor 的個數 ,
c: -XX:+UseParallelOldGC
指定在 Old Generation 使用 parallel collector
d: -XX:+UseParNewGC
指定在 New Generation 使用 parallel collector, 是 UseParallelGC 的 gc 的升級版本 , 有更好的性能或者優勢 , 能夠和 CMS gc 一塊兒使用
e: -XX:+CMSParallelRemarkEnabled
在使用 UseParNewGC 的狀況下 , 儘可能減小 mark 的時間
f: -XX:+UseConcMarkSweepGC
指 定在 Old Generation 使用 concurrent cmark sweep gc,gc thread 和 app thread 並行 ( 在 init-mark 和 remark 時 pause app thread). app pause 時間較短 , 適合交互性強的系統 , 如 web server
g: -XX:+UseCMSCompactAtFullCollection
在使用 concurrent gc 的狀況下 , 防止 memory fragmention, 對 live object 進行整理 , 使 memory 碎片減小
h: -XX:CMSInitiatingOccupancyFraction=<n>
指示在 old generation 在使用了 n% 的比例後 , 啓動 concurrent collector, 默認值是 68, 如 :-XX:CMSInitiatingOccupancyFraction=70
i: -XX:+UseCMSInitiatingOccupancyOnly
指示只有在 old generation 在使用了初始化的比例後 concurrent collector 啓動收集
3:others
a: -XX:MaxTenuringThreshold=<n>
指 定一個 object 在經歷了 n 次 young gc 後轉移到 old generation 區 , 在 linux64 的 java6 下默認值是 15, 此參數對於 throughput collector 無效 , 如 :-XX:MaxTenuringThreshold=31
b: -XX:+DisableExplicitGC
禁止 java 程序中的 full gc, 如 System.gc() 的調用. 最好加上麼, 防止程序在代碼裏誤用了。對性能形成衝擊。
c: -XX:+UseFastAccessorMethods
get,set 方法轉成本地代碼
d: -XX:+PrintGCDetails
打應垃圾收集的狀況如 :
[GC 15610.466: [ParNew: 229689K->20221K(235968K), 0.0194460 secs] 1159829K->953935K(2070976K), 0.0196420 secs]
e: -XX:+PrintGCTimeStamps
打應垃圾收集的時間狀況 , 如 :
[Times: user=0.09 sys=0.00, real=0.02 secs]
f: -XX:+PrintGCApplicationStoppedTime
打應垃圾收集時 , 系統的停頓時間 , 如 :
Total time for which application threads were stopped: 0.0225920 seconds
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html