1. 程式人生 > >JVM虛擬機——垃圾收集算法

JVM虛擬機——垃圾收集算法

進行 blog 復雜 一定的 周期 地方法 垃圾 空間 對象計數

原文博客鏈接:http://www.cnblogs.com/leesf456/p/5218594.html

1.哪些內存需要進行垃圾回收

  對於虛擬機中線程私有的區域,如程序計數器、虛擬機棧、本地方法棧都不需要進行垃圾回收,因為它們是自動進行的,隨著線程的消亡而消亡,不需要我們去回收,比如棧的棧幀結構,當進入一個方法時,就會產生一個棧幀,棧幀大小也可以借助類信息確定,然後棧幀入棧,執行方法體,退出方法時,棧幀出棧,於是其所占據的內存空間也就被自動回收了。而對於虛擬機中線程共享的區域,則需要進行垃圾回收,如堆和方法區,線程都會在這兩個區域產生自身的數據,占據一定的內存大小,並且這些數據又可能會存在相互關聯的關系,所以,這部分的區域不像線程私有的區域那樣可以簡單自動的進行垃圾回收,此部分區域的垃圾回收非常復雜,而垃圾回收也主要是針對這部分區域。

2.垃圾收集算法

  任何垃圾收集算法都必須做兩件事情。首先,它必須檢測出垃圾對象。其次,它必須回收垃圾對象所使用的堆空間並還給程序。那麽問題來了,如何檢測出一個對象是否為垃圾對象呢?一般有兩種算法解決這個問題。1. 引用計數算法 2. 可達性分析算法。

1.引用計數算法

堆中的每一個對象有一個引用計數,當一個對象被創建,並把指向該對象的引用賦值給一個變量時,引用計數置為1,當再把這個引用賦值給其他變量時,引用計數加1,當一個對象的引用超過了生命周期或者被設置為新值時,對象的引用計數減1,任何引用計數為0的對象都可以被當成垃圾回收。當一個對象被回收時,它所引用的任何對象計數減1,這樣,可能會導致其他對象也被當垃圾回收。

  問題:很難檢測出對象之間的額相互引用(引用循環問題)

2.可達性分析算法

  此算法的基本思想就是選取一系列GCRoots對象作為起點,開始向下遍歷搜索其他相關的對象,搜索所走過的路徑成為引用鏈,遍歷完成後,如果一個對象到GCRoots對象沒有任何引用鏈,則證明此對象是不可用的,可以被當做垃圾進行回收。

  那麽問題又來了,如何選取GCRoots對象呢?在Java語言中,可以作為GCRoots的對象包括下面幾種:

    1. 虛擬機棧(棧幀中的局部變量區,也叫做局部變量表)中引用的對象。

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

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

    4. 本地方法棧中JNI(Native方法)引用的對象。

  下面給出一個GCRoots的例子,如下圖,為GCRoots的引用鏈。

技術分享

  由圖可知,obj8、obj9、obj10都沒有到GCRoots對象的引用鏈,即便obj9和obj10之間有引用鏈,他們還是會被當成垃圾處理,可以進行回收。

JVM虛擬機——垃圾收集算法