GC:垃圾收集器算法
Minor GC:新生代GC,指發生在新生代的垃圾收集動做,全部的Minor GC都會觸發全世界的暫停(stop-the-world),中止應用程序的線程,不過這個過程很是短暫。數組
Major GC/Full GC:老年代GC,指發生在老年代的GC。安全
JVM:Java Virtual Machine(Java虛擬機)的縮寫。多線程
>堆併發
衆所周知,全部經過new建立的對象的內存都在堆中分配,堆被劃分爲新生代和老年代,新生代又被進一步劃分爲Eden和Survivor區,而Survivor由FromSpace和ToSpace組成。jvm
新生代:新建立的對象都是用新生代分配內存,Eden空間不足時,觸發Minor GC,這時會把存活的對象轉移進Survivor區。函數
老年代:老年代用於存放通過屢次Minor GC以後依然存活的對象。佈局
結構圖以下:性能
>棧
每一個線程執行每一個方法的時候都會在棧中申請一個棧幀,每一個棧幀包括局部變量區和操做數棧,用於存放這次方法調用過程當中的臨時變量、參數和中間結果。
>本地方法棧
用於支持native方法的執行,存儲了每一個native方法調用的狀態。
>方法區
存放了要加載的類信息、靜態變量、final類型的常量、屬性和方法信息。JVM用持久代(PermanetGeneration)來存放方法區。
以上是JVM內存組成結構。
JVM分別對新生代和老年代採用不一樣的垃圾回收機制。
GC 觸發條件:Eden區滿了觸發Minor GC,這時會把Eden區存活的對象複製到Survivor區,當對象在Survivor區熬過必定次數的Minor GC以後,就會晉升到老年代(固然並非全部的對象都是這樣晉升的到老年代的),當老年代滿了,就會報OutofMemory異常。
新生代的GC(Minor GC):
新生代一般存活時間較短基於Copying算法進行回收,所謂Copying算法就是掃描出存活的對象,並複製到一塊新的徹底未使用的空間中,對應於新生代,就是在Eden和FromSpace或ToSpace 之間copy。新生代採用空閒指針的方式來控制GC觸發,指針保持最後一個分配的對象在新生代區間的位置,當有新的對象要分配內存時,用於檢查空間是否足夠,不夠就觸發GC。當連續分配對象時,對象會逐漸從Eden到Survivor,最後到老年代。
在執行機制上JVM提供了串行GC(SerialGC)、並行回收GC(ParallelScavenge)和並行GC(ParNew):
串行GC
在整個掃描和複製過程採用單線程的方式來進行,適用於單CPU、新生代空間較小及對暫停時間要求不是很是高的應用上,是client級別默認的GC方式,能夠經過-XX:+UseSerialGC來強制指定。
並行回收GC
在整個掃描和複製過程採用多線程的方式來進行,適用於多CPU、對暫停時間要求較短的應用上,是server級別默認採用的GC方式,可用-XX:+UseParallelGC來強制指定,用-XX:ParallelGCThreads=4來指定線程數。
並行GC
與老年代的併發GC配合使用。
老年代的GC(Major GC/Full GC):
老 年代與新生代不一樣,老年代對象存活的時間比較長、比較穩定,所以採用標記(Mark)算法來進行回收,所謂標記就是掃描出存活的對象,而後再進行回收未被 標記的對象,回收後對用空出的空間要麼進行合併、要麼標記出來便於下次進行分配,總之目的就是要減小內存碎片帶來的效率損耗。
在執行機制上JVM提供了串行 GC(Serial MSC)、並行GC(Parallel MSC)和併發GC(CMS)。
串行GC(Serial MSC)
client模式下的默認GC方式,可經過-XX:+UseSerialGC強制指定。每次進行所有回收,進行Compact,很是耗費時間。
並行GC(Parallel MSC)(吞吐量大,可是GC的時候響應很慢)
server模式下的默認GC方式,也可用-XX:+UseParallelGC=強制指定。能夠在選項後加等號來制定並行的線程數。
併發GC(CMS)(響應比並行gc快不少,可是犧牲了必定的吞吐量)
使 用CMS是爲了減小GC執行時的停頓時間,垃圾回收線程和應用線程同時執行,可使用-XX:+UseConcMarkSweepGC=指定使用,後邊接 等號指定併發線程數。CMS每次回收只停頓很短的時間,分別在開始的時候(Initial Marking),和中間(Final Marking)的時候,第二次時間略長。CMS一個比較大的問題是碎片和浮動垃圾問題(Floating Gabage)。碎片是因爲CMS默認不對內存進行Compact所致,能夠經過 -XX:+UseCMSCompactAtFullCollection。
虛擬機給每一個對象定義了一個對象年齡(Age)計數器。若是對象在Eden出生並通過第一次Minor GC後仍然存活,而且能被Survivor容納的話,將被移動到Survivor區,並將對象年齡設爲 1。對象在Survivor區中每熬過一次Minor GC,年齡就增長1,當它的年齡增長到必定程度(默認爲15)時,就會被晉升到老年代中。對象晉升老年代的年齡閾值,能夠經過參數 -XX:MaxTenuringThreshold 來設置。
GC判斷對象是否"存活"或"死去"(GC回收的對象)
1.引用計數器算法
給對象中添加一個引用計數器,每當有一個地方引用它時,計數器的值加1;當引用失效時,計數器的值減;當該對象的計數器的值爲0時,標誌該對象失效。
2.跟搜索算法
基本思路:經過一系列的名爲「GC Roots」的對象做爲起始點,從這些節點開始向下搜索,搜索過的路徑稱爲引用鏈,當一個對象到GC Roots沒有任何引用鏈相連(用圖論的話來講就是從GC Roots到這個對象不可達)時,則證實對象是不可用的。
附JVM GC組合方式:
-XX:Max-PermSize
也會OOM下圖是jvm中具體的建立對象實例
分配內存有指針碰撞(已用的未用的分兩邊,經過修改中間指針的偏移量) 和 空閒列表(Free List)
public class StackAllocation { public StackAllocation obj; //逃逸 public StackAllocation getStackAllocation() { return null == obj ? new StackAllocation() : obj; } //爲成員變量賦值,逃逸 public void setStackAllocation() { obj = new StackAllocation(); } //引用成員變量的值,逃逸 public void useStackAllocation1() { StackAllocation obj = getStackAllocation(); } //對象的做用於僅在方法體內,未逃逸 public void useStackAllocation2() { StackAllocation obj = new StackAllocation; } }
-XX:SurvivorRatio
調整.當執行一次Minor GC,Eden中存活的對象會被複制到To Suvivor空間內,而且以前經歷過一次Minor GC並在From Suvivor存活下來的對象若是還年輕的話會被複制到To Suvivor.
知足兩種特殊狀況,Eden和From空間的存活對象不會被複制到To空間.
-XX:MaxTenuringThreshold
所指的的閾值時,會直接晉升到老年代中.這些新生代和老年代的GC算法能夠自由組合
兩個很是重要的概念:串行仍是並行回收,併發仍是"Stop-the-World"機制
-XX:+UseSerialGC
-XX:+UseParNewGC
-XX:GCTimeRatio
設置內存回收的時間所佔JVM運行總時間的比例(也就是控制GC的執行頻率,公式爲1/(1+N),默認值是99,也就是說將只有1%的時間用於執行垃圾回收)-XX:MaxGCPauseMillis
設置STW的暫停時間閾值,若是指定了該選項,Parallel收集器將會盡量地在指定時間範圍完成內存回收.-XX:UseAdaptiveSizePolicy
用於甚至GC的自動分代大小調整策略,這個JVM就是自動調整相關參數-XX:+UseCMSCompactAtFullCollection
,用於在執行完指定的FullGC以後是否對內存空間進行壓縮整理.-XX:CMSFullGCsBeforeCompaction
用於設置執行多少次Full GC以後對內存空間進行壓縮整理-XX:CMSInitiatingOccupancyFraction
用於設置當老年代的內存使用率達到多少的時候執行內存回收.(缺省92%) 注意 這裏的內存回收僅限於老年代,因此能夠有效的下降FullGC的次數