JVM那些事兒(七)-----類加載機制

一,類加載機制

虛擬機把描述類的數據從Class文件加載到內存,并對數據進行校驗,轉換解析和初始化,最終形成可以被虛擬機直接使用的Java類型,這就是虛擬機的類加載機制

二,類加載的時機----什么時候類進行加載?
  • 遇到new,getstatic,putstatic和invokestatic這四條字節碼指令時,如果沒有進行過初始化,則需要先觸發其初始化
    • new:使用new關鍵字實例化對象的時候
    • getstatic:設置一個類的靜態字段
    • putstatic:讀取一個類的靜態字段
      若靜態字段被final修飾,已經在編譯期把結果放入常量池的靜態字段除外
    • 調用一個類的靜態方法的時候
  • 使用java.lang.reflect包的方法對類進行反射調用的時候,如果類沒有進行過初始化,則需要先觸發其初始化
  • 當初始化一個類的時候,如果發現其父類還沒有進行過初始化,則需要先觸發其父類初始化
  • 當虛擬機啟動時,用戶需要指定一個要執行的主類(包含main()方法的那個類),虛擬機會先初始化這個主類
  • 當使用JDK1.7的動態語言支持時,如果一個java.lang.invoke.MethodHandle實例最后的解析結果REF_getstatic, REF_putstatic, REF_invokestatic的方法句柄,并且這個方法句柄所對應的類沒有進行過初始化,則需要先觸發其初始化

需要注意的是:

1,對于靜態字段,只有直接定義這個字段的類才會被初始化,因此通過子類來引用父類中定義的靜態字段,
只會觸發父類的初始化而不會觸發子類的初始化
2,常量(final)在編譯階段會存入調用類的常量池中,本質上并沒有直接引用到定義常量的類,因此不會
觸發定義常量的類的初始化
3,當接口初始化時,并不要求其父接口全部都完成了初始化,只有在真正使用到父接口的時候(如引用接口
中定義的常量)才會初始化.
三,類加載的過程

java虛擬機中類加載的全過程----加載,鏈接(驗證,準備,解析),初始化
1,加載
在加載階段,虛擬機需要完成以下三件事情

  • 通過一個類的全限定名來獲取定義此類的二進制字節流
  • 將這個字節流所代表的靜態存儲結構轉化為方法區的運行時數據結構
  • 在內存中生成一個代表這個類的java.lang.Class對象,作為方法區這個類的各種數據的訪問入口

2,驗證

  • 文件格式驗證
    主要是驗證字節流是否符合Class文件格式的規范
  • 元數據驗證
    對字節碼描述的信息進行語義分析,保證其描述的信息符合Java語言規范的要求
    -字節碼驗證
    通過數據流和控制流分析,確定程序語義是合法的,符合邏輯的
  • 符號引用驗證
    虛擬機將符號引用轉化為直接引用的時候,這個轉化動作將在解析階段發生

3,準備
準備階段是正式為類變量分配內存并設置初始化值的階段.這些變量所使用的內存都將在方法區中進行分配

4,解析

  • 類或接口的解析
  • 字段解析
  • 類方法解析
  • 接口方法解析

5,初始化
初始化階段是執行類構造器<clinit>()方法的過程

  • <clinit>()方法怎么生成的呢?
    <clinit>()方法是由編譯器自動收集類中的所有類變量的賦值動作和靜態語句塊塊(static{})中的語句合并產生的,編譯器收集的順序是由語句在源文件中出現的順序所決定的,靜態語句塊只能訪問到定義在靜態語句塊之前的變量;定義在他之后的變量,在前面的靜態語句塊可以賦值,但是不能訪問.
  • <clinit>()方法的一些特點
    • <clinit>()方法與類的構造方法(或者說實例構造器<init>())不同,他不需要顯式地調用父類構造器,虛擬機會保證子類的<clinit>()方法執行之前,父類的<clinit>()已經執行完畢. 因此在虛擬機中第一個被執行<clinit>()的類是java.lang.Object
    • 由于父類的<clinit>()方法先執行,也就意味著父類中定義的靜態語句塊要優先于子類的變量賦值操作
    • <clinit>()對于類或接口來說不是必須的,如果一個類中沒有靜態語句塊,也沒有對靜態變量的賦值操作**,那么編譯器可以不為這個類生成<clinit>()
    • 接口中不能使用靜態語句塊,但仍然有變量初始化的賦值操作,因此接口與類一樣都會生成<clinit>()方法.但是接口與類不同,執行接口的<clinit>()方法不需要先執行父接口的<clinit>()方法.只有當父接口中定義的變量使用時,父接口才會初始化.另外,接口的實現類在初始化時也一樣不會執行接口的<clinit>()方法.
  • 虛擬機會保證一個類的<clinit>()方法在多線程環境中被正確的執行
四,練習題

1,打印結果是什么?

class SingleTon {
    private static SingleTon singleTon = new SingleTon();
    public static int count1;
    public static int count2 = 0;
 
    private SingleTon() {
        count1++;
        count2++;
    }
 
    public static SingleTon getInstance() {
        return singleTon;
    }
}
 
public class Test {
    public static void main(String[] args) {
        SingleTon singleTon = SingleTon.getInstance();
        System.out.println("count1=" + singleTon.count1);
        System.out.println("count2=" + singleTon.count2);
    }
}

2,打印結果是什么?

public class Test {

    public static int k = 0;
    public static Test t1 = new Test("t1");
    public static Test t2 = new Test("t2");
    public static int i = print("i");
    public static int n = 99;
    private int a = 0;
    public int j = print("j");
    {
        print("構造塊");
    }
    static {
        print("靜態塊");
    }

    public Test(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;
        ++n;
    }

    public static int print(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++n;
        return ++i;
    }

    public static void main(String args[]) {
        Test t = new Test("init");
    }

}

參考:
1,<<深入理解Java虛擬機 JVM高級特性與最佳實踐 第二版 周志明>>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內容