《java虛擬機》----垃圾收集、內存分配

No1:java

程序計數器、虛擬機棧、本地方法棧3個區域隨線程而生,隨線程而滅:棧中的棧幀隨着方法的進入和退出而有條不紊的執行着出棧和入棧操做。每個棧幀中分配多少內存基本上市在類結構肯定下來時就已知的,所以這幾個區域的內存分配和回收都具有肯定性,在這幾個區域內就不須要過多考慮回收的問題,由於方法結束或者線程結束時,內存天然就跟隨着回收了。算法

而java堆和方法區則不同,一個接口中的多個實現類須要的內存可能不同,一個方法中的多個分支須要的內存也可能不同,咱們只有在程序處於運行期間才能知道會建立哪些對象,這部份內存的分配和回收都是動態的,垃圾收集器所關注的是這部份內存。數組

No2:安全

引用計數算法:給對象中添加一個引用計數器,當有一個地方引用它時,計數器就+1,當引用失效,則-1,任什麼時候刻計數器爲0的對象就是不可能再被使用的。多線程

No3:併發

可達性分析算法:基本思路就是經過一系列的稱爲「GC Roots」的對象做爲起始點,從這些節點開始向下搜索,搜索所走過的路徑稱爲引用鏈,當一個對象到GC Roots沒有任何引用鏈相連時,則證實此對象是不可用的。性能

在java語言中,可做爲GC Roots的對象包括下面幾種:spa

1.虛擬機棧(棧幀中的本地變量表)中引用的對象線程

2.方法區中類靜態屬性引用的對象對象

3.方法區中常量引用的對象

4.本地方法中JNI引用的對象

No4:

1.強引用就是指在程序代碼中廣泛存在的,只要強引用還存在,垃圾收集器永遠不會回收掉被引用的對象

2.軟引用描述一些還有用但並不是必需的對象。在系統將要發生內存溢出出異常以前,將會把這些對象列進回收範圍之中進行第二次回收。

3.弱引用也是描述非必需對象。當垃圾收集器工做時,不管當前內存是否足夠,都會回收掉只被弱引用關聯的對象

4.爲一個對象設置虛引用關聯的惟一目的就是能在這個對象被收集器回收時收到一個系統通知。

No5:

可達性分析算法

第一次收集:當對象可達性分析後發現沒有與GC Roots相連,則進行第一次篩選:沒有複寫finalize()方法或已經調用過finalize()方法,則進行標記爲沒有必要執行;若是斷定爲有必要執行finalize()方法,則對象將被放置在一個F-Queue隊列中

第二次收集:只要對象在finalize()中從新與引用鏈上任何一個對象創建關聯便可移除「即將回收」的集合,若是沒有逃脫,基本就真的被回收了

No6:

在堆中,新生代進行一次垃圾收集通常可回收70%~95%的空間,而永久代的垃圾收集效率遠低於此。

永久代的垃圾收集主要回收兩部份內容:廢棄常量和無用的類。

No7:

類須要同時知足下面3個條件才能算是「無用的類」:

1.該類全部的實例都已經被回收,也就是java堆中不存在該類的任何實例

2.加載該類的ClassLoader已經被回收

3.該類對應的java.lang.Class對象沒有在任何地方被引用,沒法再任何地方經過反射訪問該類的方法

No8:

垃圾收集算法:標記-清除算法

兩個不足:

1.效率問題。標記和清除兩個過程的效率都不高

2.空間問題。標記清除猴會產生大量不連續的內存碎片,空間碎片太多可能會致使須要分配大對象時,沒法找到足夠的連續內存而不得不提早出發一次垃圾收集動做

No9:

垃圾收集算法:複製算法(爲了解決效率而生)

將內存分爲大小相等的兩塊,每次只用其中一塊,當其中一塊用完,就將存活對象複製到另一塊上面,而後將原內存空間一次清理掉。代價是內存縮小爲原來的一半,另外較多的複製也會將效率變低

因此此算法經常使用來回收新生代

No10:

垃圾收集算法:標記-整理算法

標記過程和標記-清除算法同樣,但後續步驟是讓全部存活對象向一端移動,而後直接清理掉端邊界之外的內存

此算法經常使用來回收老年代

No11:

分代收集算法:新生代選用複製算法,老年代選用標記-清除或標記-整理算法

No12:

安全點設置:

1.搶先式中斷:GC發生時,先中斷全部線程,發現有線程不在安全點上,就恢復跑到安全點。這種方式已經不用了

2.主動式中斷:僅僅簡單設置一個標誌,各個線程執行時主動輪詢這個標誌,發現標誌爲真就本身中斷掛起,輪詢標誌地方和安全點是重合的。

No13:

安全區域是指在一段代碼片斷之中,引用關係不會發生變化。在這個區域中的任意地方開始GC都是安全的。

No14:

收集器:Serial收集器(單線程收集器)

特色:簡單而高效

經常使用來回收新生代,收集幾十兆甚至一兩百兆的新生代,停頓時間徹底可控制在十幾毫秒最多一百多毫秒之內。

No15:

收集器:ParNew收集器(Serial的多線程版本)

新生代首選收集器

No16:

並行(Parallel):多條垃圾收集線程並行工做,但此時用戶線程仍然處於等待狀態

併發(Concurrent):用戶線程與垃圾收集線程同時執行(不必定是並行的,可能會交替執行),用戶程序在繼續運行,而垃圾收集程序運行於另外一個CPU上。

No17:

收集器:Parrel Scavenge收集器(新生代收集器,使用複製算法,並行多線程)

它的目標是達到一個可控制的吞吐量(吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間))

高吞吐量能夠高效率的利用CPU時間,儘快完成程序的運算任務,主要適合在後臺運算而不須要太多交互的任務

虛擬機會根據當前系統的運行狀況收集性能監控信息,動態調整這些參數以提供最合適的停頓時間或者最大的吞吐量,這種調節方式稱爲GC自適應的調節策略。自適應調節策略也是Parallel Scavenge收集器與ParNew收集器的一個重要區別。

No18:

收集器:Serial Old是Serial收集器的老年代版本(單線程,使用標記-整理算法)

No19:

收集器:Parallel Old收集器(Parallel Scavenge收集器的老年代版本,多線程、使用標記整理算法)

No20:

收集器:CMS收集器(標記-清除算法)

是一種以獲取最短回收停頓時間爲目標的收集器

步驟:

1.初始標記  僅僅標記GC Roots能直接關聯到的對象

2.併發標記  進行GC Roots Tracing的過程(耗時最長)

3.從新標記  修正併發標記期間因用戶程序繼續運做而致使標記產生變更的那一部分對象的標記記錄

4.併發清除  

優勢:併發低停頓

缺點:1.當CPU不足4個時,CMS會佔用一半的運算能力去執行收集器線程,致使用戶程序的執行速度突然下降了50%

2.沒法處理浮動垃圾,可能出現Concurrent Mode Failure(併發模式失敗)失敗而致使另外一次Full GC的產生,這樣停頓的時間就很長了

浮動垃圾:CMS併發清理階段用戶線程還在運行着,伴隨程序運行天然就會有新的垃圾不斷產生,這部分垃圾出如今標記過程以後,CMS沒法在當次收集處理掉他們,只好留待下一次GC時再清理掉。

3.當空間碎片太多而提早觸發Full GC時,停頓時間也會變長

No21:

收集器:G1收集器

特色:

1.併發與並行  充分利用CPU、多核環境下的硬件優點,使用多個CPU來縮短Stop-The-World停頓的時間

2.分代收集  

3.空間整合  總體上基於標記-整理算法,局部(兩個Region之間)基於複製算法

4.可預測的停頓  創建可預測的停頓時間模型,能明確指定在長度爲M毫秒的時間片斷內,垃圾收集消耗時間不得超過N毫秒

運做步驟  1.初始標記  2.併發標記  3.最終標記  4.篩選回收

每一個Region都有一個與之對應的Remembered Set,相似對象引用的標示符,爲了不全堆掃描

No22:

新生代GC(Minor GC):發生在新生代的垃圾收集動做,由於java對象大多都具有朝生夕滅的特性,因此Minor GC很是頻繁,通常回收速度也比較快

老年代GC(Major GC/Full GC):發生在老年代的GC,出現了Major GC,常常會伴隨至少一次的Minor GC(但非絕對的,在Parallel Scavenge收集器的收集策略裏就有直接進行Major GC的策略選擇過程),Major GC的速度通常會比Minor GC慢10倍以上

No23:

內存分配和回收策略

1.對象優先在新生代Eden區中分配:當Eden區沒有足夠空間時,虛擬機將發起一次Minor GC

2.大對象直接進入老年代(最典型的大對象就是那種很長的字符串以及數組)

3.長期存活的對象將進入老年代:對象在Survivor區中沒熬過一次Minor GC,年齡就增長1歲,當年齡增長到默認15歲時晉升爲老年代

4.動態對象年齡斷定:若是Survivor空間中相同年齡全部對象大小總和大於Survivor空間的一半,年齡大於或等於該年齡的對象就能夠直接進入老年代

5.空間分配擔保:當出現大量對象在Minor GC後仍然存活的狀況,就須要老年代進行分配擔保,把Survivor沒法容納的對象直接進入老年代,不然將嘗試進行一次Full GC;(由於新生代使用複製收集算法)

101

相關文章
相關標籤/搜索