java gc的工做原理、如何優化GC的性能、如何和GC進行有效的交互

java gc的工做原理、如何優化GC的性能、如何和GC進行有效的交互

    一個優秀的Java 程序員必須瞭解GC 的工做原理、如何優化GC的性能、如何和GC進行有效的交互,由於有一些應用程序對性能要求較高,例如嵌入式系統、實時系統等。只有全面提高內存的管理效 率,才能提升整個應用程序的性能。 本篇文章首先簡單介紹GC的工做原理,而後再對GC的幾個關鍵問題進行深刻探討,最後提出一些Java程序設計建議,從GC角度提升Java程序的性能。
GC的基本原理
    Java 的內存管理實際上就是對象的管理,其中包括對象的分配和釋放,對於程序員來講,分配對象使用new關鍵字;釋放對象時,只要將對象全部引用賦值爲null,讓程序不可以再訪問到這個對象,咱們稱該對象爲"不可達的".GC將負責回收全部"不可達"對象的內存空間。
對於GC來講,當程序員建立對象時,GC就開始監控這個對象的地址、大小以及使用狀況。一般,GC採用有向圖的方式記錄和管理堆(heap)中的全部對 象,經過這種方式肯定哪些對象是"可達的",哪些對象是"不可達的"。當GC肯定一些對象爲"不可達"時,GC就有責任回收這些內存空間。可是,爲了保證 GC可以區別平臺實現的問題,Java規範標準對GC的不少行爲都沒有進行嚴格的規定。例如,對於採用什麼類型的回收算法、何時進行回收等重要問題都 沒有明確的規定。所以,不一樣的JVM的實現者每每有不一樣的實現算法。這也給Java程序員的開發帶來不少不肯定性。本文研究了幾個和GC工做相關的問題, 努力減小這種不肯定性給Java程序帶來的負面影響。
@@增量式GC( Incremental GC )
    GC在JVM中一般由一個或一組進程來實現,它自己也和用戶程序同樣佔用heap空間,運行時也佔用CPU,當GC進程運行時,應用程序中止運行。所以, 當GC運行時間較長時,用戶可以感到Java程序的停頓,另外一方面,若是GC運行時間過短,可能對象回收率過低,這意味着還有不少應該回收的對象沒有被回 收,仍然佔用大量內存。所以,在設計GC的時候,就必須在停頓時間和回收率之間進行權衡。
一個好的GC實現容許用戶定義本身所須要的設置,例如內存有限的設備,對內存的使用量很是敏感,但願GC可以準確的回收內存,它並不在乎程序速度的放慢, 另一些實時網絡遊戲,就不可以容許程序有長時間的中斷。 增量式GC就是經過必定的回收算法,把一個長時間的中斷,劃分爲不少個小的中斷,經過這種方式減小GC對用戶程序的影響。雖然,增量式GC在總體性能上可 能不如普通GC的效率高,可是它可以減小程序的最長停頓時間。
Sun JDK提供的HotSpot JVM就能支持增量式GC。HotSpot JVM缺省GC方式爲不使用增量GC,爲了啓動增量GC,咱們必須在運行Java程序時增長-Xincgc的參數。HotSpot JVM增量式GC,實現是採用Train GC算法,它的基本想法:將堆中的全部對象按照建立和使用狀況進行分組(分層),將使用頻繁和具備相關性的對象放在一隊中,隨着程序的運行,不斷對組進行 調整,當GC運行時,它老是先回收最老的(最近不多訪問的)對象,若是整組都爲可回收對象,GC將整組回收,這樣,每次GC運行只回收必定比例的不可達對 象,保證程序的順暢運行。
finalize()函數
    finalize是位於Object類的一個思路方法,該思路方法的訪問修飾符爲protected,因爲全部類爲Object的子類,所以用戶類很容易 訪問到這個思路方法。因爲,finalize函數沒有自動實現鏈式調用,咱們必須手動實現,所以finalize函數的最後一個語句一般是 super.finalize()。經過這種方式,咱們能夠實現從下到上實現finalize的調用,即先釋放本身的資源,而後再釋放父類的資源。
根據Java語言規範標準,JVM保證調用finalize函數以前,這個對象是不可達的,可是,JVM不保證這個函數必定會被調用。另外,規範標準還保證finalize函數最多運行一次。
不少Java初學者會認爲這個思路方法相似和C++中的析構函數,將不少對象、資源的釋放都放在這一函數裏面。其實,這不是一種很好的方式,緣由以下:其 一,GC爲了可以支持finalize函數,要對覆蓋這個函數的對象做不少附加的工做;其二,在finalize運行完成以後,該對象可能變成可達 的,GC還要再檢查一次該對象是不是可達的,所以,使用finalize會下降GC的運行性能;其三,因爲GC調用finalize的時間是不肯定的,因 此經過這種方式釋放資源也是不肯定的。
一般,finalize用於一些不容易控制,而且很是重要資源的釋放,例如一些I/O操做、數據鏈接等,這些資源的釋放對整個應用程序是很是關鍵的。在這 種狀況下,程序員應該以經過程序自己管理(包括釋放)這些資源爲主,以finalize函數釋放資源方式爲輔,造成一種雙保險的管理機制,而不該該僅僅依 靠finalize來釋放資源。
 程序如何和GC進行交互(不懂...)
    Java2加強了內存管理功能,增長了一個java.lang.ref包,其中定義了3種引用類。這3種引用類分別爲SoftReference、 WeakReference和PhantomReference.經過使用這些引用類,程序員能夠在必定程度和GC進行交互,以便改善GC的工做效率。這 些引用類的引用強度介於可達對象和不可達對象之間。
 一些Java編碼的建議
    根據GC的工做原理,咱們能夠經過一些竅門技巧和方式,讓GC運行更加有效率,更加符合應用程序的要求。如下就是一些程序設計的幾點建議:
一、最基本的建議就是儘早釋放無用對象的引用。大多數程序員在使用臨時變量的時候,都是讓引用變量在退出活動域(scope)後自動設置爲null。咱們 在使用這種方式時候,必須特別注意一些複雜的對象圖,例如數組、隊列、樹、圖等,這些對象之間有相互引用,關係較爲複雜。對於這類對象,GC回收它們通常 效率較低。若是程序容許,儘早將不用的引用對象賦爲null。這樣能夠加速GC的工做。
二、儘可能少用finalize函數。Finalize函數是Java提供給程序員一個釋放對象或資源的機會,可是,它會加大GC的工做量,所以儘可能少採用finalize方式回收資源。
三、注意集合數據類型,包括數組、樹、圖、鏈表等數據結構,這些數據結構對GC來講回收更爲複雜。另外,注意一些全局的變量,以及靜態變量,這些變量每每容易引發懸掛對象(dangling reference),形成內存浪費。
四、當程序有必定的等待時間,程序員能夠手動執行System.gc(),通知GC運行,可是Java語言規範標準並不保證GC必定會執行,此時使用增量式GC能夠縮短Java程序的暫停時間。
html

 

 

java 當GC進程運行時,應用程序中止運行嗎??

對於建立大量對象的大型應用程序,JVM 花在垃圾收集(GC)上的時間會很是多。默認狀況下,進行 GC 時,整個應用程序都必須等待它完成,這可能要有幾秒鐘甚至更長的時間(Java 應用程序啓動器的命令行選項 -verbose:gc 將致使向控制檯報告每一次 GC 事件)。要將這些由 GC 引發的暫停(這可能會影響快速任務的執行)降至最少,應該將應用程序建立的對象的數目降至最低。一樣,在單獨的 JVM 中運行計劃代碼是有幫助的。同時,能夠試用幾個微調選項以儘量地減小 GC 暫停。例如,增量 GC 會盡可能將主收集的代價分散到幾個小的收集上。固然這會下降 GC 的效率,可是這多是時間計劃的一個可接受的代價
資料引用:http://www.knowsky.com/362375.html
java

 

 

Java虛擬機優化選項,GC說明

引用 http://blog.sina.com.cn/s/blog_6d003f3f0100lmkn.html 程序員

 

 

有許多 JVM 選項會影響基準測試。比較重要的選項包括:算法

   * JVM 的類型:服務器(-server)與客戶機(-client)。
    * 確保有足夠的內存可用(-Xmx)。
    * 使用的垃圾收集器類型(高級的 JVM 提供許多調優選項,可是要當心使用)。
    * 是否容許類垃圾收集(-Xnoclassgc)。默認設置是容許類 GC;使用 -Xnoclassgc 可能會損害性能。
    * 是否執行 escape 分析(-XX:+DoEscapeAnalysis)。
    * 是否支持大頁面堆(-XX:+UseLargePages)。
    * 是否改變了線程堆棧大小(例如,-Xss128k)。
    * 使用 JIT 編譯的方式:老是使用(-Xcomp)、從不使用(-Xint)或只對熱點使用(-Xmixed;這是默認選項,產生的性能最好)。
    * 在執行 JIT 編譯以前(-XX:CompileThreshold)、後臺 JIT 編譯期間(-Xbatch)或分級的 JIT 編譯期間(-XX:+TieredCompilation)收集的剖析數據量。
    * 是否執行偏向鎖(biased locking,-XX:+UseBiasedLocking);注意,JDK 1.6 及更高版本會自動執行這個特性。
    * 是否激活最近的試驗性性能調整(-XX:+AggressiveOpts)。
    * 啓用仍是禁用斷言(-enableassertions 和 -enablesystemassertions)。
    * 啓用仍是禁用嚴格的本機調用檢查(-Xcheck:jni)。
    * 爲 NUMA 多 CPU 系統啓用內存位置優化(-XX:+UseNUMA)。

Class Data Sharing類共享.
java5引入了類共享機制,指在java程序第一次啓動時, 優化一些最經常使用的基礎類到一個共享文件中,暫只支持Client VM和serialGC.存放在client/classes.jsa中, 這就是爲何程序在第一次執行較慢的緣由.  開啓參數-Xshare.

J2SE 6(代號:Mustang野馬)主要設計原則之一就是提高J2SE的性能和擴展能力,主要經過最大程度提高運行效率,更好的垃圾收集和一些客戶端性能來達到。

一、偏向鎖(Biased locking)
Java 6之前加鎖操做都會致使一次原子CAS(Compare-And-Set)操做,CAS操做是比較耗時的,即便這個鎖上實際上沒有衝突,只被一個線程擁 有,也會帶來較大開銷。爲解決這一問題,Java 6中引入偏向鎖技術,即一個鎖偏向於第一個加鎖的線程,該線程後續加鎖操做不須要同步。大概的實現以下:一個鎖最初爲NEUTRAL狀態,當第一個線程加 鎖時,將該鎖的狀態修改成BIASED,並記錄線程ID,當這一線程進行後續加鎖操做時,若發現狀態是BIASED而且線程ID是當前線程ID,則只設置 一下加鎖標誌,不須要進行CAS操做。其它線程若要加這個鎖,須要使用CAS操做將狀態替換爲REVOKE,並等待加鎖標誌清零,之後該鎖的狀態就變成 DEFAULT,經常使用舊的算法處理。這一功能可用-XX:-UseBiasedLocking命令禁止。

二、鎖粗化(Lock coarsening)
若是一段代碼常常性的加鎖和解鎖,在解鎖與下次加鎖之間又沒幹什麼事情,則能夠將屢次加加鎖解鎖操做合併成一對。這一功能可用-XX:-EliminateLocks禁止。

三、自適應自旋(Adaptive spinning)
通常在多CPU的機器上加鎖實現都會包含一個短時間的自旋過程。自旋的次數不太好決定,自旋少了會致使線程被掛起和上下文切換增長,自旋多了耗CPU。爲此Java 6中引入自適應自旋技術,即根據一個鎖最近自旋加鎖成功機率動態調整自旋次數。

四、經常使用大內存分佈的堆(large page heap)
在大內分頁是x86/amd64架構上用來減少TLB(虛擬地址到物理地址翻譯緩存)大小的TLB失配率。Java 6中的內存堆可使用這一技術。

五、提升數組拷貝性能
對每種類型大小寫一個定製的彙編數組拷貝程序。

六、後臺進行代碼優化
Background Compilation in HotSpot™ Client Compiler: 後臺進行代碼優化

七、線性掃描寄存器分配算法(Linear Scan Register Allocation):
一種新的寄存器分配策略,基於SSA(static single assignment),性能提升10%左右。經常使用的寄存器分配算法將寄存器分配看做圖着色問題,時間複雜度是O(n^4),不適用於Java的JIT編譯。原來的JVM裏是根據一些本地啓發式規則來分配寄存器,效果不太好,Java 6中使用的線性掃描寄存器算法可以達到與圖顏色算法類似的效果,而且時間複雜度是線性的。

八、並行縮並垃圾收集器(Parallel Compaction Collector)
進行Full GC時使用並行垃圾收集(JDK 5裏原來非Full GC是並行的但Full GC是串行的),使用-XX:+UseParallelOldGC開啓這一功能

九、並行低停頓垃圾收集器(Concurrent Low Pause Collector)
顯式調用gc(如System.gc)時也能夠並行進行標記-清掃式垃圾收集,使用-XX:+ExplicitGCInvokesConcurrent開啓。

十、Ergonomics in the 6.0 Java Virtual Machine
自動調整垃圾收集策略、堆大小等配置,這一功能在JDK 5中加入,JDK 6中獲得顯著加強,SPECjbb2005性能提升70%。

十一、boot類裝載器的優化
jre中增長一個描述package所在jar文件的元索引文件,加快classloader加載類性能,提升桌面Java應用啓動速度(+15%)。內存佔用也減小了10%

十二、圖形程序優化
在jvm啓動以前顯示splash。

OutOfMemoryError是內存溢出, 有多種狀況會出現內存溢出.
1.java堆溢出java.lang.OutOfMemoryError: Java heap space.
2.java永久堆溢出,一般是反射,代理用的較多致使類生成過多,java.lang.OutOfMemoryError: PermGen space.
3.本地堆溢出,這多是因爲操做系統沒法分配足夠的內存,多是系統已無內存,還多是java進程內存空間耗盡,這裏有點意思,通常32位系統進程只 有4G地址空間,而又由於java實現使用本地堆或內存映射區做爲java堆的存儲空間,再去除內核映射區,java使用的堆通常只有2G之內,而若是 java堆xmx佔的過大,致使jni的本地堆太小,也會生成內存溢出.本地堆能夠是jni用new, malloc,也多是DirectBuffer等實例.
java.lang.OutOfMemoryError: request <size> bytes for <reason>. Out of swap space?
這時候,若是java堆足夠用的話, 減小xmx的值,反而會解決這種問題.
4.jni方法的溢出.而前者是由jvm檢測的本地溢出,而此是在jni方法調用時,沒法分配內存.
java.lang.OutOfMemoryError: <reason> <stack trace> (Native method)

   
JDK7性能優化.

1.(Zero Based )Compressed OOPS
在64位CPU中, JVM的OOP(Ordinary object pointer)爲64位, 簡單的講,OOP能夠被認爲爲對象的引用,雖然java中基本類型位數是固定的, 但引用類型(簡化的C語言指針)用於指向堆中的地址很天然的會被擴展成機器的字長. 32位系統最大可訪問內存爲4G,爲了突破這個限制64位系統已經很常見,可是單單引用從32位轉爲64位,堆空間佔用大概會增長一半,雖然內存已經很便宜, 可是內存帶寬,CPU緩存代價是很昂貴的.

Compressed OOPS壓縮可管理的引用到32位以下降堆的佔用空間,在JVM執行時加入編/解碼指令,相似於8086的段管理,其使用
<narrow-oop-base(64bits)> + (<narrow-oop(32bits)> << 3) + <field-offset>公式肯定內存地址.
JVM在將對象存入堆時編碼,在堆中讀取對象時解碼.

而Zero based compressed oops則進一步將基地址置爲0(並不必定是內存空間地址爲0, 只是JVM相對的邏輯地址爲0,如可用CPU的寄存器相對尋址) 這樣轉換公式變爲:
(<narrow-oop << 3) + <field-offset>
從而進一步提升了性能.不過這須要OS的支持.
若是java堆<4G,oops使用低虛擬地址空間,而並不須要編/解碼而直接使用.

Zero based compressed oops針對不一樣的堆大小使用多種策略.
1.堆小於4G,無需編/解碼操做.
2.小於32G而大於4G,使用Zero based compressed oops
3.大於32G, 不使用compressed oops.

Escape Analysis Improvements
當變量(或者對象)在方法中分配後,其指針有可能被返回或者被全局引用,這樣就會被其餘過程或者線程所引用,這種現象稱做指針(或者引用)的逃逸 (Escape),也就是說變量不只僅在本方法內使用. Java對象通常被認爲老是在堆中分配的, 這使得任何對象都須要進行垃圾回收.而大多數狀況下,方法內的對象僅在本方法中使用,徹底可使用棧來存儲,棧內變量釋放是最天然,性能最好的,C中的 struct即在分配在棧中.若是實現引用逃逸分析,即可以把沒有引用逃逸的對象分配在棧中,並且沒必要在語言上加入新的定義方法,引用逃逸分析是自動 了.JDK7已經開始缺省支持的逃逸分析了.另此還能夠消除同步,若是其分析得知對象爲非引用逃逸,則全部該對象的同步操做均可以被取消(固然這本是程序 員的任務,好比StringBuffer),另可優化對象的部分甚至所有都保存在CPU寄存器內.

NUMA Collector Enhancements
NUMA(Non Uniform Memory Access),NUMA在多種計算機系統中都獲得實現,簡而言之,就是將內存分段訪問,相似於硬盤的RAID,Oracle中的分簇,JVM只不過對此加以應用而矣.

以上三個特性也能在有些JDK6中打開,具體須要看各版本的changenotes. java6中加入了諸如如下的性能優化手段:
輕量鎖 使用cas機制減小鎖的性能消耗.
偏向鎖(biased locking)
鎖粗化(lock coarsening)
由逸出(escape)分析產生的鎖省略    逸出分析還可以分配內存在棧中,以減小內存回收的壓力.
自適應自旋鎖(adaptive spinning) 自旋鎖只有在物理多CPU中才會效果.
鎖消除(lock elimination)

在多核CPU中,鎖的獲取比單核系統耗費資源相對大的多, 由於在多核系統中,鎖的獲取須要CPU阻塞數據總線,高速緩存寫回.
這樣有時候, 咱們在單核系統中,常常會獲得StringBuffer與StringBuilder性能差很少的用例,  並且因爲有了鎖消除等技術, 有些狀況在多核CPU中也會獲得性能相差很少的狀況.

據信Java7還將缺省支持OpenGL的加速功能.

在JDK1.5中加入了Class Data Sharing, 也就是把部分經常使用的java基本類,緩存在文件或共享內存中, 以供全部java進程使用.

從JRE1.5中,java程序啓動時,如非使用-client|server指令顯示指定,虛擬機會自動選擇對應的VM,如在64位系統中,只實現了serverVM,全部的虛擬機都會使用server VM. 32位的系統則windows缺省使用clientVM,而Linux,solaris則根據CPU個數和內存來肯定是否使用serverVM,如jre6以2CPU,2GB物理內存爲界.

GC
衡量GC效率的參數主要有兩個,一個是吞吐量(即效率),一個是停頓時間,另外還有footprint,就是佔用的堆大小.

GC算法.
  1.拷貝,將全部仍然生存的對象搬到另一塊內存後,整塊內存就可回收。這種方法有效率,但須要有必定的空閒內存,拷貝也有開銷.
  2.跟蹤收集器,跟蹤收集成追蹤從根節點開始的對象引用圖。基本的追蹤算法叫做「標記並清除」,也就是垃圾收集的兩個階段。標記階段,垃圾收集器遍歷引用 數,標記每個遇到的對象。清除階段,未被標記的對象被釋放。可能在對象自己設置標記,要麼就是用一個獨立的位圖來設置標記。 壓縮(可選),垃圾收集同 時要應對碎片整理的任務。標記和清除一般使用兩種策略來消除堆碎片:壓縮和拷貝,這兩種方法都是快速移動對象來減少碎片, 加在一塊兒叫作mark-sweep-compact.
  3.還有一種引用計數收集器,這種方法時堆中的每一個對象都有一個引用計數,在引用賦值時加1,置空或做爲基本類型的引用超出生命期(如方法退出而棧回收)時減1,其對多個對象的循環引用無能爲力,但引用計數都不爲0 ,還有引用數的增減帶來額外開銷,故已再也不使用.
 
分代收集器
   根據程序的統計, 大多數對象生命週期都很短,都很快被釋放掉.但也有部分對象生命週期較長, 甚至永久有效. 對於拷貝算法來講,每次收集時,全部的活動對象都要移動來移動去。對於短生命的對象還好說,常常能夠就地解決掉,但是對於長生命週期的對象就純粹是個體力 勞動了,把它挪來挪去除消耗大量的時間,沒有產生任何效益。分代收集能直接讓長生命週期的對象長時間的呆在一個地方按兵不動。GC 的精力能夠更多的花在收集短命對象上。
  這種方法裏,堆被分紅兩個或更多的子堆,每個堆爲一「代」對象服務。最年幼的那一代進行最頻繁的垃圾收集。由於多數對象是短命的,只有很小部分的年 幼對象能夠在經歷第一次收集後還存活。若是一個最年幼的對象經歷了好幾回垃圾收集後還是活着的,那這個對象就成爲壽命更高的一代,它被轉移到另一個子堆 中去。年齡更高一代的收集沒有年輕一代來得頻繁。每當對象在所屬的年齡代中變得成熟(屢次垃圾收集後仍倖存)以後,就能夠轉移到更高年齡的一代中去。
  分代收集通常在年輕堆中應用於拷貝算法,年老代應用於標記清除算法。無論在哪一種狀況下,把堆按照對象年齡分組能夠提升最基本的垃圾收集的性能。 

通常java中分代收集器將堆分爲年輕代, 年老代和永久代. 年輕代的收回稱爲minorGC,由於在此期內,對象生命週期很較,故效率較高, 年老代稱爲FullGC,對應的效率較低,用時較長,應儘可能減小FullGC的次數.

VM,
Client VM 適合桌面程序,啓動快, 運行時間短, 故其不會預先裝入太多的類,對類進行過多優化.
Server VM 適合服務程序,啓動時間不重要,運行時間較長, 會預先裝入大多基礎類,對類進行優化.

GC種類.
Serial 串行回收器(缺省)
在GC運行時, 應用邏輯所有暫停,利用單線程經過"拷貝"進行年輕代的垃圾收集,單線程使用"標記-清除-壓縮"進行年老代(tenured)垃圾回收. 吞吐率較高.適合單CPU硬件.

Parallel  並行回收器
針對年輕代使用多個GC線程進行"拷貝"垃圾收集,針對年輕代的GC運行時,程序暫停, 年老代依然是單線程使用"標記-清除-壓縮"進行年老代垃圾回收,GC運行時, 應用一樣暫停.在大內存,多處理器的機器上,能夠考慮使用此Parallel GC(使用參數-XX:+UseParallelGC指定),這種GC在對YoungGen進行GC時,能夠對多處理器加以利用,從而相對下降了停頓時間,但重點是提升了吞吐量,可是,在其對OldGen進行GC時,依然使用了和Serial GC一樣的算法。因此在Jdk5U6中,又引入了Parallel Compacting Collector(使用參數-XX:+UseParallelOldGC指定),這種GC對OldGen的GC也能夠受益於多處理器。因爲對OldGen的GC遠比YoungGen更耗時間,因此理論上這種Garbage Collector能夠提供更優的性能,並且,值得注意的是,Parallel Compacting GC最終會取代Parallel GC。

Concurrent mark-sweep 併發回收器.
對於年輕代使用和多GC線程"拷貝"回收,此GC也須要暫停應用,但因爲minorGC效率較高,故不會產生大的停頓,對於年老代使用與應用程序同時運行 的併發方式標記-回收機制,其將步驟再次分細,部分階段(初始標記,從新標記)也會徹底致使應用暫停,但時間較短,大部分時間都是應用程序與單GC線程並 發,下降了應用程序暫停的時間。這種GC使用了和Parallel GC一致的YoungGen的收集算法,而在對OldGen進行GC時,它採用了較爲複雜的算法,提供了極短的停頓時間。可是,複雜的算法也形成了更大的 開銷,並且這種 Parallel GC是non-compacting的,因此它使用一個空閒塊鏈表來管理OldGen Heap,分配空間的開銷也加大了.在某些場景中,較短的停頓時間比較大的吞吐量更加劇要,這時能夠考慮使用此GC,即所謂的CMS GC。

增量收集器(Train算法)已逐漸被棄用,-XincGC 在1.5中會選中併發GC.

在SUN J2SE 5.0中,引入了所謂Behavior-based Parallel Collector Tuning,這種調優方式基於三個Goal:

Maximum Pause Time Goal: 使用參數-XX:MaxGCPauseMillis=n指定,默認值爲空。這個參數被指定後,三個內存區的GC停頓時間都會盡力的保持在n毫秒之內,若是沒法知足,則相應的內存區會縮小,以縮短GC的停頓時間;

Throughput Goal: 使用參數-XX:GCTimeRatio=n指定,默認值爲99,即GC時間佔總的應用運行時間爲1%。若是沒法知足,相應的內存區會擴大,以提升應用在兩次GC間的運行時間;

Footprint Goal: 因爲眼下內存氾濫,因此這個Goal通常就不值得關注了;

這三個Goal的優先級爲從上到下,即首先知足Maximum Pause Time Goal,再知足Throughput Goal,最後再知足Footprint Goal。

 
使用參數-Xloggc:file和-XX:+PrintGCDetails打印gclog,而後使用gcviewer對gclog進行查看,它的優點在於能夠生成統計數據,吞吐量,最大的和最小的停頓時間,Full GC時間佔整個GC時間的百分比等,均可以使用這個工具查看,但目前只支持到1.5。

JConsole是容許您監測各類各樣的VM資源運行時使用狀況的Java監視和管理控制檯。實際在java5中, 須要加一個參數, 在java6中因爲支持了attach API,jconsole會自動加載JVM內部的JMX代理.
jstat命令打印各類各樣的VM統計數據,包括內存使用、垃圾回收時間、類加載和及時編譯器統計。 jmap 命令容許您得到運行時的堆直方圖和堆轉儲。jhat命令容許您分析堆轉儲。jstack命令容許您得到線程堆棧跟蹤。這些診斷工具能夠附加到任何應用程序,不須要以特別方式啓動。
 

引用 http://blog.sina.com.cn/s/blog_6d003f3f0100lmkn.htmlwindows

相關:觸發Full GC執行的狀況四種狀況數組

相關文章
相關標籤/搜索