1. 程式人生 > >jvm如何判斷物件是否可以被回收

jvm如何判斷物件是否可以被回收

內容基本來自周志明 深入理解java虛擬機器 第二版 第三章 。這本書還可以,不過好像也沒什麼其他中文的關於jvm比較好的書了

jvm要做垃圾回收時,首先要判斷一個物件是否還有可能被使用。那麼如何判斷一個物件是否還有可能被用到?

如果我們的程式無法再引用到該物件,那麼這個物件就肯定可以被回收,這個狀態稱為不可達。當物件不可達,該物件就可以作為回收物件被垃圾回收器回收。

那麼這個可達還是不可達如何判斷呢?

答案就是GC roots ,也就是根物件,如果從一個物件沒有到達根物件的路徑,或者說從根物件開始無法引用到該物件,該物件就是不可達的。

以下三類物件在jvm中作為GC roots,來判斷一個物件是否可以被回收
(通常來說我們只要知道虛擬機器棧和靜態引用就夠了)

  • 虛擬機器棧(JVM stack)中引用的物件(準確的說是虛擬機器棧中的棧幀(frames))
    我們知道,每個方法執行的時候,jvm都會建立一個相應的棧幀(棧幀中包括運算元棧、區域性變量表、執行時常量池的引用),棧幀中包含這在方法內部使用的所有物件的引用(當然還有其他的基本型別資料),當方法執行完後,該棧幀會從虛擬機器棧中彈出,這樣一來,臨時建立的物件的引用也就不存在了,或者說沒有任何gc roots指向這些臨時物件,這些物件在下一次GC時便會被回收掉

  • 方法區中類靜態屬性引用的物件
    靜態屬性是該型別(class)的屬性,不單獨屬於任何例項,因此該屬性自然會作為gc roots。只要這個class存在,該引用指向的物件也會一直存在。class 也是會被回收的,在面後說明

  • 本地方法棧(Native Stack)引用的物件

一個class要被回收準確的說應該是解除安裝,必須同時滿足以下三個條件

  • 堆中不存在該類的任何例項
  • 載入該類的classloader已經被回收
  • 該類的java.lang.Class物件沒有在任何地方被引用,也就是說無法通過反射再帶訪問該類的資訊

這篇內容太少了,在說幾句java中的四種引用型別

其實這四類引用的區別就在於GC時是否回收該物件

  • 強引用(Strong) 就是我們平時使用的方式 A a = new A();強引用的物件是不會被回收的
  • 軟引用(Soft) 在jvm要記憶體溢位(OOM)時,會回收軟引用的物件,釋放更多記憶體
  • 弱引用(Weak) 在下次GC時,弱引用的物件是一定會被回收的
  • 虛引用(Phantom) 對物件的存在時間沒有任何影響,也無法引用物件實力,唯一的作用就是在該物件被回收時收到一個系統通知