gc原理以及gc日誌剖析

gc原理以及gc日誌java

一.概述算法

學習Java的咱們都知道垃圾收集(gc),大部分人把這項技術看成是java語言的伴生產物。事實上,gc的歷史比Java久遠,1960年誕生於MIT的Lisp是第一門真正使用內存動態分配和垃圾收集技術的語言。那咱們今天就研究下垃圾收集原理。安全

二.對象已死嗎?數據結構

Java的垃圾回收主要是對推內存的回收,裏面存放着Java幾乎全部的對象實例,垃圾回收以前是要肯定哪些還「存活」哪些已經「死去」。學習

1.引用計數器法spa

給對象添加一個引用計數器,每當有地方對他進行引用時計數器值➕1;當引用失效時,計數器值就➖1,任什麼時候候計數器值爲0的時候表示對象不可能在使用的。線程

2.可達性分析算法3d

經過一系列稱爲「GC Roots」的對象做爲起點,從這些節點往下搜索,搜索所走過的路徑稱爲「引用鏈」,當一個對象到「GC Roots」沒有任何引用鏈相連時,則證實對象不可用的日誌

代碼示例:對象

gc日誌以下:

咱們很明顯的看到gc日誌中6092K->456K,意味着虛擬機並無由於這兩個對象互相引用而不回收他們,因此java虛擬機使用的是可達性分析算法標記的。

其實即便被可達性分析算法標記的不可達對象也不是必定會被回收的,虛擬機會對這些對象進行一次篩選,篩選的條件是此對象是否有必要執行finalize()方法。當對象沒有覆蓋finalize()方法或者finalize()已經被虛擬機調用過,虛擬機將這兩種狀況視爲「沒有必要執行」。若是對象被斷定有必要執行finalize()方法是並在finalize()中與「GC Roots」創建關聯則次對象不會被回收了。

三.垃圾回收算法

咱們知道了虛擬機怎麼標記一個對象是否可用,那他怎麼進行回收的呢?其實堆內存能夠分爲新生代和老年代,新生代又被劃分爲一個Eden和兩個Survivor區域他們的比例爲8:1:1,不一樣的垃圾收集器廠商給對這兩個區域給出了不一樣的算法。

1.新生代——複製算法

新生代對象的特色就是,大部門對象在一次GC中會被回收掉,因此使用的是複製算法:新生代每次建立對象的時候只會使用一個Eden和其中的一塊Survivor,在垃圾回收時將存活的對象複製到另一塊Survivor區域,最後清理掉Eden和剛纔的Survivor區域。

1.老年代——標記-整理算法

老年代通常保存的是一些大對象,或者不被常常回收的對象,根據特色使用的標記-整理算法:如同名字同樣,算法分爲"標記"和「整理」兩個階段:首先先標記出全部須要回收的對象,在標記完成後統一回收因此被標記的對象進行整理,將被標記的對象都向一端移動,而後直接清理掉邊界之外的內存。

四.HotSpot算法實現

上面說了咱們怎麼標記對象「死亡」和怎麼進行垃圾回收的,但在HotSpot虛擬機在實現這些算法上是必須對算法的執行效率進行考量的。

1.安全點

在可達性分析中對執行的時間的敏感體如今GC停頓上,其意思是在整個分析的過程當中看起來就像被凍結在某一個時間點上的,不能夠出現分析的過程當中引用關係在不斷變化,若是這點得不到保證則分析的結果的準確性就得不到保障。這點是致使在GC進行時須要停頓全部的java執行線程。當執行系統停頓下來後,虛擬機並不須要所有上小文和全局全部的位置,虛擬機經過一個OopMap的數據結構在類加載的時候將對象的偏移量數據信息記錄下來,因此GC掃描是就直接獲得這些信息的。其實這些經過指令被加入進行記載對象信息的OopMap位置也叫作安全點,程序執行時並不是全部點均可以停下來開始GC的,只有在到達安全點才能停頓。安全點機制程序執行中,在不太長的時間內會遇到可進入GC的安全點。在實際中會遇到在GC時有線程再也不執行,例如線程被掛起了。這是咱們須要安全區域去解決。

2.安全區域

安全區域是指在一段代碼片斷中,引用關心不會發生變化。在這個區域中的任意地方開始GC都是安全的。在代碼執行到安全區域是,首先表示這直接進去安全區域,這樣虛擬機在這段時間GC時就不用管那些標記爲安全區域的線程了。當離開安全區域時首先得判斷是GC分析是否完成,沒完成則須要等待。

五.理解GC日誌

這是上圖打印的gc日誌

[GC (System.gc()) [PSYoungGen: 6092K->448K(38400K)] 6092K->456K(125952K), 0.0051702 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]

PSYoungGen表示的是新生代gc不一樣垃圾收集器新生代名稱不同,6092K->448K(38400K)表示新生代大小的變化,6092K->456K(125952K)表示推內存的大小變化 後面表示用時。

[Full GC (System.gc()) [PSYoungGen: 448K->0K(38400K)] [ParOldGen: 8K->378K(87552K)] 456K->378K(125952K), [Metaspace: 3050K->3050K(1056768K)], 0.0056045 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]

表示發生在老年代的gc(Major GC/Full GC) 他知識爲伴隨一次的新生代的gc(Minor GC),448K->0K(38400K)表示新生代內存變化,8K->378K(87552K) 老年代gc變化,456K->378K(125952K)表示gc先後堆內存的變化。

相關文章
相關標籤/搜索