1. 程式人生 > >JVM——Java內存區域相關2

JVM——Java內存區域相關2

虛擬 清理 二次 glib ade 元數據 回收 code java

一. 對象的創建

在語言層面上,創建對象的方式有克隆、反序列化、new等方法。

1.1 檢查類是否被加載

虛擬機遇到一條new指令時,首先去檢查這個指令的參數是否能夠在常量池中定位到一個類的符號引用,並且檢查這個符號引用代表的類是否已被加載、解析和初始化過。如果沒有,那必須先執行相應的類加載過程。

1.2 分配內存

  • 指針碰撞(Bump the Pointer):同步(CAS或者TLAB),內存碎片問題。
  • 空閑列表(Free List)

1.3 初始化為零值(不包括對象頭)。

1.4 設置對象信息

這個對象是哪個類的實例、如何才能找到類的元數據信息、對象的哈希碼、對象的GC分代年齡等信息,這些信息存放在對象的對象頭中。

1.5 執行類的構造函數

二. 可達性分析算法

在主流的商用程序語言都是通過可達性分析來判定對象是否存活。引用技術算法很難解決對象之間的循環引用問題。

這個算法的基本思想是通過一系列稱為“GC Roots”的對象作為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈,當一個對象到GC Roots沒有任何引用鏈相連時,就證明此對象是不可用的。

在Java語言中,可作為GC Roots的對象包括下面幾種:

  • 虛擬機棧(棧幀中的本地變量表)中的引用對象。
  • 方法區中的類靜態屬性引用的對象。
  • 方法區中常亮引用的對象。
  • 本地方法棧中JNI(即一般說的Native方法)引用的對象。

在可達性分析中不可達的對象,也並不會被立即銷毀。要真正宣告一個對象死亡,至少(多??)要經歷兩次標記過程。覆蓋了finalize()方法且沒有被調用的類的實例將會被放到一個隊列中依次執行finalize()方法。第二次被掃描到該對象就會被真正銷毀。

三. 回收方法區

永久代的垃圾回收主要回收兩部分內容:廢棄常量和無用的類。回收廢棄常量與回收Java堆中的對象非常類似。只要這個常量沒有被引用,那麽必要的話這個常量就會被系統清理出常量池。而要判定一個類是否是“無用的類”的條件就苛刻得多:

  • 該類所有的實例都已經被回收,也就是Java堆中不存在該類的任何實例。
  • 加載該類的ClassLoader已經被回收。
  • 該類對應的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。

虛擬機可以對滿足了上述3個條件的無用類進行回收,但同時還它也受HotSopt虛擬機提供的-Xnoclassgc參數控制。

在使用大量反射、動態代理、CGLib等ByteCode框架、動態生成JSP以及OSGi這類頻繁自定義ClassLoader的場景都需要虛擬機具備類卸載的功能,以保證永久代不會溢出。

JVM——Java內存區域相關2