1. 程式人生 > >《JVM》(四)Class類文件結構,對象的創建

《JVM》(四)Class類文件結構,對象的創建

style 使用 kit 數列 初始 text nor 分配 b-s

Class類文件結構

class文件是一組以8字節為單位的二進制流,只有兩種數據類型:無符號數(基本數據類型),表(復合數據類型)

魔數

版本號

常量池(占class空間最大的數據之一,從1開始計數)

1.字面量 :接近於java層面的常量概念,如字符串,聲明為final的常量

2.符號引用:類和接口的全限定名,字段和方法的描述符

字段描述符:描述字段數據類型

方法描述符:描述方法參數列表和返回值

訪問標誌

類索引,父類索引,接口索引集合

字段表集合(描述接口或類中聲名的變量,不包括方法中的局部變量)

方法表集合

屬性表集合(如,方法表,屬性表都可以帶有自己的屬性表,如code屬性存方法的代碼信息)


對象的創建(非Class類對象)

0.準備工作,這個指令的參數是否可以在常量池中定位到一個類的符號引用,檢查這個類是否已經被加載,解析初始化,如果沒有,先執行相應的類加載過程

1.分配內存(堆中)

2.分配的內存空間都初始化為零值

3.init根據程序員的意願初始化


分配內存

對象所需內存的大小在類加載完成後便完全確定(JVM可以通過普通Java對象的類元數據信息確定對象大小);

為對象分配內存相當於把一塊確定大小的內存從Java堆裏劃分出來

1. 指針碰撞

如果Java堆是絕對規整的:一邊是用過的內存,一邊是空閑的內存,中間一個指針作為邊界指示器;

分配內存只需向空閑那邊移動指針,這種分配方式稱為"指針碰撞"(Bump the Pointer);

2. 空閑列表

如果Java堆不是規整的:用過的和空閑的內存相互交錯;

需要維護一個列表,記錄哪些內存可用;

分配內存時查表找到一個足夠大的內存,並更新列表,這種分配方式稱為"空閑列表"(Free List);

Java堆是否規整由JVM采用的垃圾收集器是否帶有壓縮功決定的;

所以,使用Serial、ParNew等帶Compact過程的收集器時,JVM采用指針碰撞方式分配內存;而使用CMS這種基於標記-清除(Mark-Sweep)算法的收集器時,采用空閑列表方式;


對象的訪問定位

1.通過句柄訪問對象

技術分享圖片

好處:reference中存的是穩定的句柄地址,在GC時對象被移動只會改變實例數據指針,而reference本身不需要改變

2.通過直接指針訪問對象

技術分享圖片

好處:訪問速度快



對象創建的時機

使用new關鍵字創建對象

使用Class類的newInstance方法(反射機制)

用Constructor類的newInstance方法(反射機制)

使用Clone方法創建對象

用(反)序列化機制創建對象

對象的初始化順序

父類靜態代碼塊,靜態成員變量

子類靜態代碼塊,靜態成員變量

父類普通成員變量,非static代碼塊

父類構造函數

子類普通成員變量,非static代碼塊

子類構造函數


類加載的時機

new關鍵字實例化對象,讀取或設置一個類的靜態字段(被final修飾除外)、調用一個類的靜態方法;

使用java.lang.reflect包的方法對類進行反射調用

初始化一個類,若其父類沒有被初始,先初始化起父類

虛擬機啟動時,執行的主類(含main方法的類)先初始化


比如,new一個對象,首先檢查Class類是否被加載,沒有,先進行類加載過程;

然後進行對象的創建,分配內存,按照順序初始化;

再次new一個對象,檢查Class類被加載過了,直接進行對象的創建;

《JVM》(四)Class類文件結構,對象的創建