Java虛擬機內存模型及垃圾回收監控調優html
若是你想理解Java垃圾回收若是工做,那麼理解JVM的內存模型就顯的很是重要。今天咱們就來看看JVM內存的各不一樣部分及若是監控和實現垃圾回收調優。java
JVM內存模型 算法
正如你上圖所看到的,JVM內存能夠劃分爲不一樣的部分,廣義上,JVM堆內存能夠劃分爲兩部分:年輕代和老年代(Young Generation and Old Generation)編程
年輕代(Young Generation)服務器
年輕代用於存放由new所生成的對象。當年輕代空間滿時,垃圾回收就會執行。這個垃圾回收咱們稱之爲 最小化垃圾回收(Minor GC)。年輕代又能夠分爲三分部: 一個Eden內存區(Eden Memory)和兩個Survivor 內存區(Survivor Memory)。多線程
關於年輕代的重點:併發
老年代(Old Generation)oracle
老年代內存包含那些通過屢次最小化GC且存活的對象。 一般當老年代內存滿時垃圾回收會被執行。咱們稱之爲大GC (Major GC),一般這個過程會花費很長的時間。jvm
Stop the World Eventjsp
全部的垃圾回收都是「阻塞」事件(「Stop the World」 events) ,由於全部應用程序線程必須中止,直到垃圾回收操做完成以後才能繼續。
因爲年輕代老是保存着短時間存活的對象,最小化GC很是快,應用程序也不會受到影響。然而大GC(Major GC)因爲它要檢查全部存活的對象,因此須要花費很長的時間。 大GC會在垃圾回收期間使得你的應用程序沒有任何響應,應最大化的減小此類GC。若是你有一個即時響應應用程序且老是有不少的大GC在執行。你會發現存在超時錯誤。
垃圾回器掃行的時間依賴於GC所使用的策略。這就是爲何對於那些高響應用程序來講,GC的監控與調優顯得很是必要。
永久代(Permanent Generation)
永久代或持久代包含JVM用來描述應用程序中使用的類和方法的元數據。注意 永久代不是JAVA堆內存的一部分。
JVM在運行期間依據應用程序所使用的類來存入永久代,同時也包含Java SE庫類各方法。 永久代中的對象經過全GC(Full GC)來進行垃圾回收。
方法區Method Area
方法區是永久代的一部分,用於存儲類結構(運行時的常量和靜態變量)及方法和構造的代碼。
運行時常量池Runtime Constant Pool
運行時常量池是類中常量池在編譯期的表示,它包含類的運行時常量,靜態方法,它是方法區的一部分。
Java棧內存Java Stack Memory
Java 棧內存用於執行線程。包含方法短時間存活的特定值及方法中所涉及的指向堆中其它對象的引用。
Java 堆內存Switches(Java Heap Memory Switches)
提供了大量的內存Switch,咱們能夠用來設置內存大小及它們的比率。一此經常使用的內存Switches以下。
VM Switch | VM Switch 描述 |
---|---|
-Xms | 設置JVM啓動時堆初始值。 |
-Xmx | 設置堆的最大值 |
-Xmn | 設置年輕代的大小 |
-XX:PermGen | 設置永久代內存的初始值 |
-XX:MaxPermGen | 設置永久代內存的最大值 |
-XX:SurvivorRatio | 用於提供Eden區和Survivor區的比例, 例如,若是年輕代的大小爲 10M,VM switch is -XX:SurvivorRatio=2 那麼 5 M 分配給 Eden 區,每個Survivor 區爲 2.5 M .默認比例大小爲 8。 |
-XX:NewRatio | 老年代/新生代的比例. 默認值是 2. |
大多數狀況下,上述選項是很是有用的。若是你也想試試其它參數能夠查看 JVM 官方主頁
JAVA GC
Java GC是從內存中標記、移除非可用對象並釋放所分配的空間用於後續建立對像的過程。Java編程語言最大的功能之一就是自動垃圾回收。不像其它相似C的編程語言,它們的內存分配與回收能夠人爲操做。
GC是後臺執行用於檢查內存中的全部對象並找出未被任務程序所引用的對象。全部這些未引用的對象將被刪除,同時空間也會被回收用於分配給其它對象。
關於標記、刪除方法有兩個問題:
1.因爲新建立的對象將會變成不可用,全部效率上不是很高。
2.屢次GC後可用的對象很能在後續的GC後仍然可用。
上述方法的不足在於Java的GC是分代的,在堆內存中分年輕代和老年代。 前面我已經解釋過基於最小化GC(Minor GC)和大GC(Major GC)對象是若是被掃描並從一個分代區移到別一個分區。
Java GC的類型
在應用程序中咱們可使用以下五種類型的GC。咱們可使用JVM相關設置爲應用程序開啓GC策略,如今咱們就來具體的看看.
G1垃圾收集器不一樣於其它收集器,它沒有年輕代、老年代空間,它將堆空間劃分紅多個相同大小的堆區域(heap regions),當調用一次垃圾回收,它首先收集實時性不是很高的區域的數據,所以稱爲」Garbage First」。有關詳細的可參考個人另一篇Blog:Java垃圾收集器之--Garbage-First Collector 。
JAVA 垃圾收集監控
咱們可使用Java命令行和UI工具來監控應用程序的垃圾收集活動。下面的例子中,我使用Java SE Downloads 中一個演示程序。
若是你想使用一樣的程序,前往 Java SE Downloads 頁面下載JDK 7 and JavaFX Demos and Samples。 我使用的和序示例是Java2Demo.jar 能夠在jdk1.7.0_55/demo/jfc/Java2D 目錄中找到。固然了這步可選。你能夠選用任何Java程序執行GC監控命令。
我使用的啓動演示程序的命令是:
1
|
pankaj@Pankaj:~
/Downloads/jdk1
.7.0_55
/demo/jfc/Java2D
$ java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseSerialGC -jar Java2Demo.jar
|
JSTAT
咱們可使用 jstat 命令行工具來監控JVM內存和GC活動。標準的JDK中含有此命令。所以能夠直接使用。
運行 jstat 以前你須要知道程序的進程ID號。你能夠運行 ps -eaf | grep java 命令來獲取。
1
2
3
|
pankaj@Pankaj:~$
ps -eaf | grep Java2Demo.jar
501 9582 11579 0 9:48PM ttys000 0:21.66
/usr/bin/java
-Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseG1GC -jar Java2Demo.jar
501 14073 14045 0 9:48PM ttys002 0:00.00
grep
Java2Demo.jar
|
個人Java程序的進程ID號爲 9582.如今咱們能夠以下執行jstat 命令。
1 pankaj@Pankaj:~$ jstat -gc 9582 1000 2 S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT 3 1024.0 1024.0 0.0 0.0 8192.0 7933.3 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 4 1024.0 1024.0 0.0 0.0 8192.0 8026.5 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 5 1024.0 1024.0 0.0 0.0 8192.0 8030.0 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 6 1024.0 1024.0 0.0 0.0 8192.0 8122.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 7 1024.0 1024.0 0.0 0.0 8192.0 8171.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654 8 1024.0 1024.0 48.7 0.0 8192.0 106.7 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656 9 1024.0 1024.0 48.7 0.0 8192.0 145.8 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656
jstat命令的最後一個參數是每次輸出的時間間隔,所以它會每隔一秒打印內存及垃圾回收數據。下面詳細看看每列。
jstat的優勢在於它能夠在無GUI的遠程服務器上執行。注意S0C, S1C 和EC之和爲 10M ,與咱們經過JVM選項 -Xmn10m 設置的值同樣。
Java VisualVM with Visual GC
若是你想在GUI下查看內存及GC操做。 那麼你可使用 jvisualvm 工具。Java VisualVM 也一樣包含在JDK中,你不須要單獨下載。
只須要運行在終端上執行jvisualvm 命令來啓動Java VisualVM程序。一旦啓動,你須要經過Tools--》Plugins選項安裝Visual GC 插件,正以下圖所示。
Visual GC 安裝完畢後,左邊列中打開程序前往Visual GC 部分。你將會獲得以下圖所示的JVM內存及GC截圖。
Java GC 調優是提升應用程序吞吐量的最後選擇,只有當你發現長時間的GC致使性能降低而產生應用程序超時。
你會在日誌中看到java.lang.OutOfMemoryError: PermGen space的錯誤信息。而後能夠嘗試監控並經過使用JVM 選項 -XX:PermGen and -XX:MaxPermGen 來增長Perm Gen內存空間。你或許也能夠嘗試使用-XX:+CMSClassUnloadingEnabled 來檢查使用CMS垃圾收集的性能如何?
若是你發現大量的FUll GC操做,你能夠試着增長老年代內存空間。
總之GC調優須要花費大量的精力和時間,這裏絕沒有什麼硬性或者快速的規則。你須要嘗試不一樣的選項,比較他們,並找對你應用程序來講最好的那個。
這就是全部有關Java內存模型和垃圾回收。我但願這有助於你理解JVM內存模型及垃圾回收的過程。謝謝。
原文連接: JournalDev 翻譯: TonySpark
譯文連接: http://www.cnblogs.com/tonyspark/p/3731696.html
[ 轉載請保留原文出處、譯者和譯文連接。]