jvm架構
java虛拟機hotspot的架構:

jvm主要組成部分:class loader(類加載器)、runtime data area(運作時資料區)、執行引擎(execution engine)。
jvm垃圾回收簡介
step 1: marking
gc算法在掃描存活對象時通常需要從root節點開始,掃描所有存活對象的引用,建構出對象圖。
root:靜态字段、方法參數、局部變量、cpu寄存器
step 2: normal deletion
删除沒有被引用的對象,釋放空間。
step 2a: deletion with compacting
删除垃圾并壓縮存活的引用對象,有利于提高記憶體配置設定的效率。
generational garbage collection(分代垃圾回收)
hotspot堆結構:
young generation:從eden區配置設定新對象,eden區滿後,發生一次minor garbage collection,把eden區和一個survivor區中存活的對象移動到另一個survivor區中,存活的對象age加1,當存活的對象age達到一個門檻值時晉升到old generation。
old generation:儲存存活長久對象的地方,old generation滿後會發生major garbage collection(full garbage collection)。
stop the world event:minor garbage collection和major garbage collection都是stop the world event,即垃圾回收的時候會暫停程式中線程的執行。
permanent generation:儲存jvm中用于描述類和方法的中繼資料資訊。
整個gc的流程總結圖:
gc分代的基本假設是:絕大部分對象的生命周期都非常短暫,存活時間短。
配置設定小對象的開銷負擔小,不要吝啬去建立。
gc最喜歡這種小而短命的對象。
讓對象的生命周期盡可能短,例如在方法體内建立,使其能盡快地在younggc中被回收,不會晉升(romote)到年老代(old generation)。
對象配置設定的優化:盡量避免大對象的配置設定,當對象大到eden generation放不下時,jvm隻能嘗試去old generation配置設定,這種情況需要盡可能避免,因為一旦在old generation配置設定,這個對象就隻能被old generation的gc或是fullgc回收了。
不可變對象可以減少gc的壓力:hotspot jvm為了提高younggc的性能,避免每次younggc都掃描old generation中的對象引用,采用了卡表(card table) 的方式。簡單來說,當old generation中的對象發生對young generation中的對象産生新的引用關系或釋放引用時,都會在卡表中響應的标記上标記為髒(dirty),而younggc時,隻需要掃描這些dirty的項就可以了。可變對象對其它對象的引用關系可能會頻繁變化,并且有可能在運作過程中持有越來越多的引用,特别是容器。這些都會導緻對應的卡表項被頻繁标記為dirty。而不可變對象的引用關系非常穩定,在掃描卡表時就不會掃到它們對應的項了。
指定容器初始化大小可以減少gc的壓力:每次容器擴容配置設定更大的空間,可能會增加gc的次數。
各類引用:java.lang.ref.reference有幾個子類,用于處理和gc相關的引用。jvm的引用類型簡單來說有幾種:
strong reference,最常見的引用。
weak reference,當沒有指向它的強引用時會被gc回收。
soft reference,隻當臨近oom時才會被gc回收。
phantom reference,主要用于識别對象被gc的時機,通常用于做一些清理工作。
garbage collector(垃圾收集器)
jvm中會在以下情況觸發回收:對象沒有被引用,作用域發生未捕捉異常,程式正常執行完畢,程式執行了system.exit(),程式發生意外終止。
jvm中标記垃圾使用的算法是一種根搜尋算法。簡單的說,就是從一個叫gc roots的對象開始,向下搜尋,如果一個對象不能達到gc roots對象的時候,說明它可以被回收了。這種算法比一種叫做引用計數法的垃圾标記算法要好,因為它避免了當兩個對象啊互相引用時無法被回收的現象。
jvm中對于被标記為垃圾的對象進行回收時又分為了一下3種算法:
1.标記清除算法,該算法是從根集合掃描整個空間,标記存活的對象,然後在掃描整個空間對沒有被标記的對象進行回收,這種算法在存活對象較多時比較高效,但會産生記憶體碎片。
2.複制算法,該算法是從根集合掃描,并将存活的對象複制到新的空間,這種算法在存活對象少時比較高效。
3.标記整理算法,标記整理算法和标記清除算法一樣都會掃描并标記存活對象,在回收未标記對象的同時會整理被标記的對象,解決了記憶體碎片的問題。
hotspot 1.6版使用的垃圾收集器如下圖(圖中兩個收集器之間有連線,說明它們可以配合使用):
1.serial gc
從名字上看,串行gc意味着是一種單線程的,是以它要求收集的時候所有的線程暫停。這對于高性能的應用是不合理的,是以串行gc一般用于client模式的jvm中。
2.parnew gc
是在serialgc的基礎上,增加了多線程機制。但是如果機器是單cpu的,這種收集器是比serialgc效率低的。
3.parrallel scavenge gc
這種收集器又叫吞吐量優先收集器,而吞吐量=程式運作時間/(jvm執行回收的時間+程式運作時間),假設程式運作了100分鐘,jvm的垃圾回收占用1分鐘,那麼吞吐量就是99%。parallel scavenge gc由于可以提供比較不錯的吞吐量,是以被作為了server模式jvm的預設配置。
4.parallelold
是老生代并行收集器的一種,使用了标記整理算法,是jdk1.6中引進的,在之前老生代隻能使用串行回收收集器。
5.serial old
是老生代client模式下的預設收集器,單線程執行,同時也作為cms收集器失敗後的備用收集器。
6.cms(concurrent mark sweep)
又稱響應時間優先回收器,使用标記清除算法,同時它又是一個使用多線程并發回收的垃圾收集器。他的回收線程數為(cpu核心數+3)/4,是以當cpu核心數為2時比較高效些。cms分為4個過程:初始标記、并發标記、重新标記、并發清除和并發重置。其中初始标記和重新标記是獨占系統資源的,而并發标記、并發清除和并發重置是可以和使用者線程一起執行的。是以,從整體上來說,cms 收集不是獨占式的,它可以在應用程式運作過程中進行垃圾回收。
7.garbage first(g1)
比較特殊的是g1回收器既可以回收young generation,也可以回收tenured generation。它是在jdk6的某個版本中才引入的,性能比較高,同時注意了吞吐量和響應時間。與cms收集器相比,g1收集器是基于标記-壓縮算法的。是以,它不會産生空間碎片,也沒有必要在收集完成後,進行一次獨占式的碎片整理工作。
對于垃圾收集器的組合使用可以通過下表中的參數指定:
參考:
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
http://coolshell.cn/articles/11541.html
http://www.ibm.com/developerworks/cn/java/j-lo-jvmgarbagecollection/index.html
http://www.importnew.com/16388.html
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。
http://www.cnblogs.com/luxiaoxun/p/4631575.html