MinorGC 和 FullGC的理解

1.GC回收機制熟悉麼,分代算法知道麼?
2.瞭解 Java 虛擬機的垃圾回收算法?html

    從年輕代空間(包括 Eden 和 Survivor 區域)回收內存被稱爲 Minor GC。 Major GC 是清理永久代。Full GC 是清理整個堆空間—包括年輕代和永久代。
> Android GC
Android GC 原理探究- http://geek.csdn.net/news/detail/193654java

> Java中的GC是什麼? 爲何要有GC?
GC目的:回收堆內存中再也不使用的對象,釋放資源
回收時間:當對象永久地失去引用後,系統會在合適的時候回收它所佔的內存。程序員

  GC System.gc()或Runtime.getRuntime().gc(),
  忘記或者錯誤的內存回收會致使程序或系統的不穩定甚至崩潰,Java提供的GC功能能夠自動監測對象是否超過做用域從而達到自動回收內存的目的。垃圾回收能夠有效的防止內存泄露,有效的使用可使用的內存。
 採用「分代式垃圾收集」。這種方法會跟Java對象的生命週期將堆內存劃分爲不一樣的區域,在垃圾收集過程當中,可能會將對象移動到不一樣區域: 
 - 伊甸園(Eden):這是對象最初誕生的區域,而且對大多數對象來講,這裏是它們惟一存在過的區域。 
 - 倖存者樂園(Survivor):從伊甸園倖存下來的對象會被挪到這裏。 
 - 終身頤養園(Tenured):這是足夠老的倖存對象的歸宿。年輕代收集(Minor-GC)過程是不會觸及這個地方的。當年輕代收集不能把對象放進終身頤養園時,就會觸發一次徹底收集(Major-GC),這裏可能還會牽扯到壓縮,以便爲大對象騰出足夠的空間。算法

  在C/C++中,釋放無用變量內存空間的事情要由程序員本身來解決。
  Java有了GC,就不須要程序員去人工釋放內存空間。當Java虛擬機發覺內存資源緊張的時候,就會自動地去清理無用變量所佔用的內存空間。固然,若是須要,程序員能夠在Java程序中顯式地使用System.gc()來強制進行一次當即的內存清理。 由於顯式聲明是作堆內存全掃描也就是 Full GC,是須要中止全部的活動的(Stop The World Collection),你的應用能承受這個嗎?而其顯示調用System.gc()只是給虛擬機一個建議,不一 定會執行,由於System.gc()在一個優先級很低的線程中執行。
  java的GC功能能夠自動監測對象是否超過做用域從而達到自動回收內存的目的,java語言沒有提供釋放已分配內存的俄顯示操做方法。在應用程序中,只要某對象變得不可達,也就是沒有根(root)引用該對象,這個對象就會成爲垃圾回收器的目標。緩存

GC的基本原理:
 1.對於程序員來講,用new關鍵字即在堆中分配了內存,咱們稱之爲「可達」。對於GC來講,只要全部被引用的對象爲null時,咱們稱之爲「不可達」,就將進行內存的回收。
 2.當一個對象被建立時,GC開始監控這個對象的大小、內存地址及使用狀況。GC採用有向圖的方式記錄和管理堆(heap)中的全部對象,經過這種方式能夠明確哪些對象是可達的,哪些不是。當肯定爲不可達時,則對其進行回收。
 3.保證GC在不一樣平臺的實現問題,java規範對其不少行爲沒有進行嚴格的規定。對於採用什麼算法,何時進行回收等。多線程

-- GC收集器有哪些?併發

1.serial收集器
單線程,工做時必須暫停其餘工做線程。多用於client機器上,使用複製算法
2.ParNew收集器
serial收集器的多線程版本,server模式下虛擬機首選的新生代收集器。複製算法
3.Parallel Scavenge收集器
複製算法,可控制吞吐量的收集器。吞吐量即有效運行時間。
4.Serial Old收集器
serial的老年代版本,使用整理算法。
5.Parallel Old收集器
第三種收集器的老年代版本,多線程,標記整理
6.CMS收集器
目標是最短回收停頓時間。7.G1收集器,基本思想是化整爲零,將堆分爲多個Region,優先收集回收價值最大的Region。函數

> Java GC,GC 算法,GC機制
內存分配過程爲(來源於《成爲JavaGC專家part I》-http://www.importnew.com/1993.html
成爲JavaGC專家Part II — 如何監控Java垃圾回收機制-http://www.importnew.com/2057.html
JDK5.0垃圾收集優化之 - http://calvin.iteye.com/blog/91905
三大Java 虛擬機垃圾回收機制的比較(HotSpot, JRockit, IBM JVM)- https://blog.csdn.net/ZYC88888/article/details/70918799
垃圾回收器,如何判斷對象是否存活- http://blog.csdn.net/TyroneRenekton/article/details/59114835?ref=myread
JVM初探- 內存分配、GC原理與垃圾收集器-- http://blog.csdn.net/zjf280441589/article/details/53946312
深刻理解JVM之一:Java內存區域: https://yq.aliyun.com/articles/14408#工具

-- 在Java中,它的內存管理包括兩方面:內存分配(建立Java對象的時候)和內存回收。瞭解JVM,才能寫出更高效,充分利用有限的內存的程序。
  Java垃圾回收主要作的是兩件事:1)內存回收; 2)碎片整理。性能

  內存管理小技巧:
  1)儘可能使用直接量,eg:String javaStr = "小學徒的成長曆程";
  2)使用StringBuilder和StringBuffer進行字符串鏈接等操做;
  3)儘早釋放無用對象;
  4)儘可能少使用靜態變量;
  5)緩存經常使用的對象:可使用開源的開源緩存實現,eg:OSCache,Ehcache;
  6)儘可能不使用finalize()方法;
  7)在必要的時候能夠考慮使用軟引用SoftReference。

-- GC回收機制算法:分代複製垃圾回收和標記垃圾回收,增量垃圾回收。

   學習Java GC機制,能夠幫助咱們在平常工做中排查各類內存溢出或泄露問題,解決性能瓶頸,達到更高的併發量,寫出更高效的程序。咱們將從4個方面學習Java GC機制:

1,內存是如何分配的;

2,如何保證內存不被錯誤回收(即:哪些內存須要回收);

3,在什麼狀況下執行GC以及執行GC的方式;

4,如何監控和優化GC機制。

--  瞭解Java GC機制,必須先清楚在JVM中內存區域的劃分。
在Java運行時的數據區裏,JVM管理的內存區域分爲幾個模塊:
  1,程序計數器(Program Counter Register):程序計數器是一個比較小的內存區域,用於指示當前線程所執行的字節碼執行到了第幾行,能夠理解爲是當前線程的行號指示器。字節碼解釋器在工做時,會經過改變這個計數器的值來取下一條語句指令。
 每一個程序計數器只用來記錄一個線程的行號,因此它是線程私有(一個線程就有一個程序計數器)的。
   若是程序執行的是一個Java方法,則計數器記錄的是正在執行的虛擬機字節碼指令地址;若是正在執行的是一個本地(native,由C語言編寫 完成)方法,則計數器的值爲Undefined,因爲程序計數器只是記錄當前指令地址,因此不存在內存溢出的狀況,所以,程序計數器也是全部JVM內存區 域中惟一一個沒有定義OutOfMemoryError的區域。

  2,虛擬機棧(JVM Stack):一個線程的每一個方法在執行的同時,都會建立一個棧幀(Statck Frame),棧幀中存儲的有局部變量表、操做站、動態連接、方法出口等,當方法被調用時,棧幀在JVM棧中入棧,當方法執行完成時,棧幀出棧。
   局部變量表中存儲着方法的相關局部變量,包括各類基本數據類型,對象的引用,返回地址等。在局部變量表中,只有long和double類型會佔用2個局部變量空間(Slot,對於32位機器,一個Slot就是32個bit),其它都是1個Slot。須要注意的是,局部變量表是在編譯時就已經肯定 好的,方法運行所須要分配的空間在棧幀中是徹底肯定的,在方法的生命週期內都不會改變。
   虛擬機棧中定義了兩種異常,若是線程調用的棧深度大於虛擬機容許的最大深度,則拋出StatckOverFlowError(棧溢出);不過多 數Java虛擬機都容許動態擴展虛擬機棧的大小(有少部分是固定長度的),因此線程能夠一直申請棧,知道內存不足,此時,會拋出 OutOfMemoryError(內存溢出)。
   每一個線程對應着一個虛擬機棧,所以虛擬機棧也是線程私有的。

  3,本地方法棧(Native Method Statck):本地方法棧在做用,運行機制,異常類型等方面都與虛擬機棧相同,惟一的區別是:虛擬機棧是執行Java方法的,而本地方法棧是用來執行native方法的,在不少虛擬機中(如Sun的JDK默認的HotSpot虛擬機),會將本地方法棧與虛擬機棧放在一塊兒使用。
  本地方法棧也是線程私有的。

  4,堆區(Heap):堆區是理解Java GC機制最重要的區域,沒有之一。在JVM所管理的內存中,堆區是最大的一塊,堆區也是Java GC機制所管理的主要內存區域,堆區由全部線程共享,在虛擬機啓動時建立。堆區的存在是爲了存儲對象實例,原則上講,全部的對象都在堆區上分配內存(不過現代技術裏,也不是這麼絕對的,也有棧上直接分配的)。
  通常的,根據Java虛擬機規範規定,堆內存須要在邏輯上是連續的(在物理上不須要),在實現時,能夠是固定大小的,也能夠是可擴展的,目前主流的虛擬機堆區都是可擴展的。若是在執行垃圾回收以後,仍沒有足夠的內存分配,也不能再擴展,將會拋出OutOfMemoryError:Java heap space異常。
    「Java內存分配機制」。

  5,方法區(Method Area):在Java虛擬機規範中,將方法區做爲堆的一個邏輯部分來對待,但事實上,方法區並非堆(Non-Heap);另外,很多人的博客中,將Java GC的分代收集機制分爲3個代:青年代,老年代,永久代,這些做者將方法區定義爲「永久代」,這是由於,對於以前的HotSpot Java虛擬機的實現方式中,將分代收集的思想擴展到了方法區,並將方法區設計成了永久代。不過,除HotSpot以外的多數虛擬機,並不將方法區當作永久代,HotSpot自己,也計劃取消永久代。本文中,因爲筆者主要使用Oracle JDK6.0,所以仍將使用永久代一詞。
  方法區是各個線程共享的區域,用於存儲已經被虛擬機加載的類信息(即加載類時須要加載的信息,包括版本、field、方法、接口等信息)、final常量、靜態變量、編譯器即時編譯的代碼等。
  方法區在物理上也不須要是連續的,能夠選擇固定大小或可擴展大小,而且方法區比堆還多了一個限制:能夠選擇是否執行垃圾收集。通常的,方法區上 執行的垃圾收集是不多的,這也是方法區被稱爲永久代的緣由之一(HotSpot),但這也不表明着在方法區上徹底沒有垃圾收集,其上的垃圾收集主要是針對常量池的內存回收和對已加載類的卸載。
  在方法區上進行垃圾收集,條件苛刻並且至關困難,效果也不使人滿意,因此通常不作太多考慮,能夠留做之後進一步深刻研究時使用。
  在方法區上定義了OutOfMemoryError:PermGen space異常,在內存不足時拋出。
  運行時常量池(Runtime Constant Pool)是方法區的一部分,用於存儲編譯期就生成的字面常量、符號引用、翻譯出來的直接引用(符號引用就是編碼是用字符串表示某個變量、接口的位置,直接引用就是根據符號引用翻譯出來的地址,將在類連接階段完成翻譯);運行時常量池除了存儲編譯期常量外,也能夠存儲在運行時間產生的常量(好比String類的intern()方法,做用是String維護了一個常量池,若是調用的字符「abc」已經在常量池中,則返回池中的字符串地址,不然,新建一個常量加入池中,並返回地址)。

  6,直接內存(Direct Memory):直接內存並非JVM管理的內存,能夠這樣理解,直接內存,就是 JVM之外的機器內存,好比,你有4G的內存,JVM佔用了1G,則其他的3G就是直接內存,JDK中有一種基於通道(Channel)和緩衝區 (Buffer)的內存分配方式,將由C語言實現的native函數庫分配在直接內存中,用存儲在JVM堆中的DirectByteBuffer來引用。 因爲直接內存收到本機器內存的限制,因此也可能出現OutOfMemoryError的異常。

-- Java對象的訪問方式。通常來講,一個Java的引用訪問涉及到3個內存區域:JVM棧,堆,方法區。
以最簡單的本地變量引用:Object obj = new Object()爲例:
  Object obj表示一個本地引用,存儲在JVM棧的本地變量表中,表示一個reference類型數據;
  new Object()做爲實例對象數據存儲在堆中;
  堆中還記錄了Object類的類型信息(接口、方法、field、對象類型等)的地址,這些地址所執行的數據存儲在方法區中;
在Java虛擬機規範中,對於經過reference類型引用訪問具體對象的方式並未作規定.

--  Java GC機制:

JVM 內置的通用垃圾回收原則。堆內存劃分爲 Eden、Survivor(年輕代) , Tenured/Old (老年代)空間:
1.Minor GC
    從年輕代空間(包括 Eden 和 Survivor 區域)回收內存被稱爲 Minor GC。可是,當發生Minor GC事件的時候,有一些有趣的地方須要注意到:
    當 JVM 沒法爲一個新的對象分配空間時會觸發 Minor GC,好比當 Eden 區滿了。因此分配率越高,越頻繁執行 Minor GC。內存池被填滿的時候,其中的內容所有會被複制,指針會從0開始跟蹤空閒內存。Eden 和 Survivor 區進行了標記和複製操做,取代了經典的標記、掃描、壓縮、清理操做。因此 Eden 和 Survivor 區不存在內存碎片。寫指針老是停留在所使用內存池的頂部。執行 Minor GC 操做時,不會影響到永久代。從永久代到年輕代的引用被當成 GC roots,從年輕代到永久代的引用在標記階段被直接忽略掉。
   質疑常規的認知,全部的 Minor GC 都會觸發「全世界的暫停(stop-the-world)」,中止應用程序的線程。對於大部分應用程序,停頓致使的延遲都是能夠忽略不計的。其中的真相就 是,大部分 Eden 區中的對象都能被認爲是垃圾,永遠也不會被複制到 Survivor 區或者老年代空間。若是正好相反,Eden 區大部分新生對象不符合 GC 條件,Minor GC 執行時暫停的時間將會長不少。
  因此 Minor GC 的狀況就至關清楚了——每次 Minor GC 會清理年輕代的內存。

2.Major GC vs Full GC
    Major GC 是清理永久代。Full GC 是清理整個堆空間—包括年輕代和永久代。
很不幸,實際上它還有點複雜且使人困惑。首先,許多 Major GC 是由 Minor GC 觸發的,因此不少狀況下將這兩種 GC 分離是不太可能的。另外一方面,許多現代垃圾收集機制會清理部分永久代空間,因此使用「cleaning」一詞只是部分正確。
   這使得咱們不用去關心究竟是叫 Major GC 仍是 Full GC,你們應該關注當前的 GC 是否中止了全部應用程序的線程,仍是可以併發的處理而不用停掉應用程序的線程。

   這種混亂甚至內置到 JVM 標準工具。下面一個例子很好的解釋了個人意思。讓咱們比較兩個不一樣的工具 Concurrent Mark 和 Sweep collector (-XX:+UseConcMarkSweepGC)在 JVM 中運行時輸出的跟蹤記錄。
   關於JVM,須要說明一下的是,目前使用最多的Sun公司的JDK中,自從 1999年的JDK1.2開始直至如今仍在普遍使用的JDK6,其中默認的虛擬機都是HotSpot。2009年,Oracle收購Sun,加上以前收購 的EBA公司,Oracle擁有3大虛擬機中的兩個:JRockit和HotSpot,Oracle也代表了想要整合兩大虛擬機的意圖,可是目前在新發布 的JDK7中,默認的虛擬機仍然是HotSpot,所以本文中默認介紹的虛擬機都是HotSpot,相關機制也主要是指HotSpot的GC機制。

-- GC機制的基本算法是:分代收集

 新生代:通常是指大批對象產生的快,消亡的也快;老生代:通常是指大批對象產生後,不容易消。
-- 年輕代:
  新生代的主要垃圾回收方法,在新生代中,使用「中止-複製」算法進行清理,將新生代內存分爲2部分,1部分 Eden區較大,1部分Survivor比較小,並被劃分爲兩個等量的部分。每次進行清理時,將Eden區和一個Survivor中仍然存活的對象拷貝到 另外一個Survivor中,而後清理掉Eden和剛纔的Survivor
    這裏也能夠發現,中止複製算法中,用來複制的兩部分並不老是相等的(傳統的中止複製算法兩部份內存相等,但新生代中使用1個大的Eden區和2個小的Survivor區來避免這個問題)
  因爲絕大部分的對象都是短命的,甚至存活不到Survivor中,因此,Eden區與Survivor的比例較大,HotSpot默認是 8:1,即分別佔新生代的80%,10%,10%。若是一次回收中,Survivor+Eden中存活下來的內存超過了10%,則須要將一部分對象分配到 老年代。用-XX:SurvivorRatio參數來配置Eden區域Survivor區的容量比值,默認是8,表明Eden:Survivor1:Survivor2=8:1:1.

-- 老年代:
    老年代存儲的對象比年輕代多得多,並且不乏大對象,對老年代進行內存清理時,若是使用中止-複製算法,則至關低效。通常,老年代用的算法是標記-整理算法,即:標記出仍然存活的對象(存在引用的),將全部存活的對象向一端移動,以保證內存的連續。
     在發生Minor GC時,虛擬機會檢查每次晉升進入老年代的大小是否大於老年代的剩餘空間大小,若是大於,則直接觸發一次Full GC,不然,就查看是否設 置了-XX:+HandlePromotionFailure(容許擔保失敗),若是容許,則只會進行MinorGC,此時能夠容忍內存分配失敗;若是不容許,則仍然進行Full GC(這表明着若是設置-XX:+Handle PromotionFailure,則觸發MinorGC就會同時觸發Full GC,哪怕老年代還有不少內存,因此,最好不要這樣作)。
    方法區(永久代),永久代的回收有兩種:常量池中的常量,無用的類信息,常量的回收很簡單,沒有引用了就能夠被回收。對於無用的類進行回收,必須保證3點:1.類的全部實例都已經被回收;2.加載類的ClassLoader已經被回收。3.類對象的Class對象沒有被引用(即沒有經過反射引用該類的地方)
   永久代的回收並非必須的,能夠經過參數來設置是否對類進行回收。HotSpot提供-Xnoclassgc進行控制,使用-verbose,-XX:+TraceClassLoading、-XX:+TraceClassUnLoading能夠查看類加載和卸載信息:
     -verbose、-XX:+TraceClassLoading能夠在Product版HotSpot中使用;
     -XX:+TraceClassUnLoading須要fastdebug版HotSpot支持。

-- 垃圾收集器

   在介紹垃圾收集器以前,須要明確一點,就是在新生代採用的中止複製算法中,「停 止(Stop-the-world)」的意義是在回收內存時,須要暫停其餘全部線程的執行。這個是很低效的,如今的各類新生代收集器愈來愈優化這一點,但仍然只是將中止的時間變短,並未完全取消中止。

  1. Serial收集器:新生代收集器,使用中止複製算法,使用一個線程進行GC,其它工做線程暫停。使用-XX:+UseSerialGC可使用Serial+Serial Old模式運行進行內存回收(這也是虛擬機在Client模式下運行的默認值)
  2. ParNew收集器:新生代收集器,使用中止複製算法,Serial收集器的多線程版,用多個線程進行GC,其它工做線程暫停,關注縮短垃圾收集時間。使用-XX:+UseParNewGC開關來控制使用ParNew+Serial Old收集器組合收集內存;使用-XX:ParallelGCThreads來設置執行內存回收的線程數。
  3. Parallel Scavenge 收集器:新生代收集器,使用中止複製算法,關注CPU吞吐量,即運行用戶代碼的時間/總時間,好比:JVM運行100分鐘,其中運行用戶代碼99分鐘,垃圾收集1分鐘,則吞吐量是99%,這種收集器能最高效率的利用CPU,適合運行後臺運算(關注縮短垃圾收集時間的收集器,如CMS,等待時間不多,因此適 合用戶交互,提升用戶體驗)。使用-XX:+UseParallelGC開關控制使用 Parallel Scavenge+Serial Old收集器組合回收垃圾(這也是在Server模式下的默認值);使用-XX:GCTimeRatio來設置用戶執行時間佔總時間的比例,默認99,即 1%的時間用來進行垃圾回收。使用-XX:MaxGCPauseMillis設置GC的最大停頓時間(這個參數只對Parallel Scavenge有效)
  4. Serial Old收集器:老年代收集器,單線程收集器,使用標記整理(整理的方法是Sweep清理和Compact壓縮,清理是將廢棄的對象幹掉,只留倖存的對象,壓縮是將移動對象,將空間填滿保證內存分爲2塊,一塊全是對象,一塊空閒)算法,使用單線程進行GC,其它工做線程暫停(注意,在老年代中進行標 記整理算法清理,也須要暫停其它線程),在JDK1.5以前,Serial Old收集器與ParallelScavenge搭配使用。
  5. Parallel Old收集器:老年代收集器,多線程,多線程機制與Parallel Scavenge差不錯,使用標記整理(與Serial Old不一樣,這裏的整理是Summary彙總和Compact壓縮,彙總的意思就是將倖存的對象複製到預先準備好的區域,而不是像Sweep(清 理)那樣清理廢棄的對象)算法,在Parallel Old執行時,仍然須要暫停其它線程。Parallel Old在多核計算中頗有用。Parallel Old出現後(JDK 1.6),與Parallel Scavenge配合有很好的效果,充分體現Parallel Scavenge收集器吞吐量優先的效果。使用-XX:+UseParallelOldGC開關控制使用Parallel Scavenge +Parallel Old組合收集器進行收集。
  6. CMS(Concurrent Mark Sweep)收集器:老年代收集器,致力於獲取最短回收停頓時間,使用標記清除算法,多線程,優勢是併發收集(用戶線程能夠和GC線程同時工做),停頓小。使用-XX:+UseConcMarkSweepGC進行ParNew+CMS+Serial Old進行內存回收,優先使用ParNew+CMS(緣由見後面),當用戶線程內存不足時,採用備用方案Serial Old收集。
  CMS收集的方法是:先3次標記,再1次清除,3次標記中前兩次是初始標記和從新標記(此時仍然須要中止(stop the world)), 初始標記(Initial Remark)是標記GC Roots能關聯到的對象(即有引用的對象),停頓時間很短;併發標記(Concurrent remark)是執行GC Roots查找引用的過程,不須要用戶線程停頓;從新標記(Remark)是在初始標記和併發標記期間,有標記變更的那部分仍須要標記,因此加上這一部分 標記的過程,停頓時間比並發標記小得多,但比初始標記稍長。在完成標記以後,就開始併發清除,不須要用戶線程停頓。
  因此在CMS清理過程當中,只有初始標記和從新標記須要短暫停頓,併發標記和併發清除都不須要暫停用戶線程,所以效率很高,很適合高交互的場合。
  CMS也有缺點,它須要消耗額外的CPU和內存資源,在CPU和內存資源緊張,CPU較少時,會加劇系統負擔(CMS默認啓動線程數爲(CPU數量+3)/4)。
  另外,在併發收集過程當中,用戶線程仍然在運行,仍然產生內存垃圾,因此可能產生「浮動垃圾」,本次沒法清理,只能下一次Full GC才清理,所以在GC期間,須要預留足夠的內存給用戶線程使用。因此使用CMS的收集器並非老年代滿了才觸發Full GC,而是在使用了一大半(默認68%,即2/3,使用-XX:CMSInitiatingOccupancyFraction來設置)的時候就要進行Full GC,若是用戶線程消耗內存不是特別大,能夠適當調高-XX:CMSInitiatingOccupancyFraction以下降GC次數,提升性能,若是預留的用戶線程內存不夠,則會觸發Concurrent Mode Failure,此時,將觸發備用方案:使用Serial Old 收集器進行收集,但這樣停頓時間就長了,所以-XX:CMSInitiatingOccupancyFraction不宜設的過大。
  還有,CMS採用的是標記清除算法,會致使內存碎片的產生,可使用-XX:+UseCMSCompactAtFullCollection來設置是否在Full GC以後進行碎片整理,用-XX:CMSFullGCsBeforeCompaction來設置在執行多少次不壓縮的Full GC以後,來一次帶壓縮的Full GC。
G1收集器:在JDK1.7中正式發佈,與現狀的新生代、老年代概念有很大不一樣,目前使用較少,不作介紹。
注意併發(Concurrent)和並行(Parallel)的區別:
     併發是指用戶線程與GC線程同時執行(不必定是並行,可能交替,但整體上是在同時執行的),不須要停頓用戶線程(其實在CMS中用戶線程仍是須要停頓的,只是很是短,GC線程在另外一個CPU上執行);
     並行收集是指多個GC線程並行工做,但此時用戶線程是暫停的;因此,Serial和Parallel收集器都是並行的,而CMS收集器是併發的.

-- 垃圾回收器經典算法:  1)Reference counting(引用計數)基本思想是:當對象建立並賦值時該對象的引用計數器置1,每當對象給任意變量賦值時,引用記數+1;一旦退出做用域則引用記數-1。一旦引用記數變爲0,則該對象能夠被垃圾回收。引用記數有其相應的優點:對程序的執行來講,每次操做只須要花費很小塊的時間。這對於不能被過長中斷的實時系統來講有着自然的優點。但也有其不足:不可以檢測到環(兩個對象的互相引用);同時在每次增長或者減小引用記數的時候比較費時間。在現代的垃圾回收算法中,引用記數已經再也不使用。  2)Mark-sweep(標記清理)基本思想是:每次從根集出發尋找全部的引用(稱爲活對象),每找到一個,則對其作出標記,當追蹤完成以後,全部的未標記對象即是須要回收的垃圾。也叫追蹤算法,基於標記並清除。這個垃圾回收步驟分爲兩個階段:在標記階段,垃圾回收器遍歷整棵引用樹並標記每個遇到的對象。在清除階段,未標記的對象被釋放,並使其在內存中可用。  3)Copying collection(複製收集)基本思想是:將內存劃分爲兩塊,一塊是當前正在使用;另外一塊是當前未用。每次分配時使用當前正在使用內存,當無可用內存時,對該區域內存進行標記,並將標記的對象所有拷貝到當前未用內存區,這是反轉兩區域,即當前可用區域變爲當前未用,而當前未用變爲當前可用,繼續執行該算法。拷貝算法須要中止全部的程序活動,而後開始冗長而繁忙的copy工做。這點是其不利的地方。  近年來還有兩種算法:  4)Generational garbage collection(分代)其思想依據是:  (1) 被大多數程序建立的大多數對象有着很是短的生存期。  (2) 被大多數程序建立的部分對象有着很是長的生存期。簡單拷貝算法的主要不足是它們花費了更多的時間去拷貝了一些長期生存的對象。而分代算法的基本思想是:將內存區域分兩塊(或更多),其中一塊表明年輕代,另外一塊表明老的一代。針對不一樣的特色,對年輕一代的垃圾收集更爲頻繁,對老代的收集則較少,每次通過年輕一代的垃圾回收總會有未被收集的活對象,這些活對象通過收集以後會增長成熟度,當成熟度到達必定程度,則將其放進老代內存塊中。分代算法很好的實現了垃圾回收的動態性,同時避免了內存碎片,是目前許多JVM使用的垃圾回收算法。  5)Conservative garbage collection(保守)

相關文章
相關標籤/搜索