JVM之類的加載+連接+初始化及反編譯

1、 JVM

  • Java Virtual Machine(Java虛擬機),JVM是一種用於計算設備的規範,它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現的。
  • 引入Java虛擬機後,Java語言在不同平臺上運行時不需要重新編譯。Java語言使用Java虛擬機屏蔽了與具體平臺相關的信息,使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(字節碼),就可以在多種平臺上不加修改地運行。

2、追蹤類的加載信息

  • 【-XX:+TraceClassLoading】(-XX:-表示關閉option選項)
  • JVM在當前啓動環境下加載類的順序在這裏插入圖片描述
    • 應用-》運行
      在這裏插入圖片描述
    • 啓動類-》父類-》主類
      在這裏插入圖片描述

3、類的加載方式

  • 類的加載、連接(驗證、準備、解析)、初始化都是在運行時完成的
    • 加載時:加載字節碼,並在內存中創建Class對象[唯一]用來封裝類在方法區的數據結構
    • 準備:爲類的靜態變量分配內存,並初始化爲默認值
    • 解析階段:把類中的符號引用(類/方法/字段名)轉爲直接(內存)引用
    • 初始化:爲類的靜態變量賦(正確)值、執行static

被動

  • 除主動外就是被動

主動

  • 首次主動加載纔會被初始化

1)new

  • 普通類直接創建實例
    加載過程:
    1)連接時(準備)a=0
    2)初始化時a=3、再加載靜態代碼塊a=4
    3)主函數創建實例,加載代碼塊a=9,加載構造函數a=18
    在這裏插入圖片描述
  • 創建子類的實例
    當一個類在初始化時,要求其父類都已經被初始化完畢。
    加載過程:
    1)連接時(準備)a=0,c=0
    2)初始化時a=3、c=3、再加載靜態代碼塊a=4、c=6
    3)創建子類實例,先加載父類代碼塊a=9、父類構造函數a=18、再加載子類代碼塊c=11、子類構造函數c=33
    在這裏插入圖片描述

2)訪問類的靜態變量/賦值、調用類的靜態方法

  • 直接訪問普通類的靜態變量
    加載過程:
    1)連接時(準備)a=0
    2)初始化時a=3,加載靜態代碼塊a=4
    在這裏插入圖片描述
  • 調用普通類的靜態方法,同上初始化+執行調用方法
    在這裏插入圖片描述

另:創建靜態實例

實例在最前面

加載過程:
1)連接時(準備)創建實例、a=0
2)初始化時加載代碼塊a=5、加載構造函數a=10,進行賦值a=3、並加載靜態代碼塊a=4
在這裏插入圖片描述

主函數再創建一個實例:

在這裏插入圖片描述

創建實例放聲明和靜態代碼塊中間

加載過程:
1)連接時(準備)a=0、創建實例
2)初始化時a=3;加載代碼塊a=8,加載構造函數a=16,加載靜態代碼塊a=17
在這裏插入圖片描述
加載過程:
1)連接時(準備)a=0,創建實例
2)初始化時a=3,加載靜態代碼塊a=4,加載代碼塊a=9,加載構造函數a=18
在這裏插入圖片描述

3)反射

  • 1、含main()類
    在這裏插入圖片描述

  • 2、普通類
    在這裏插入圖片描述

  • 3、子類
    在這裏插入圖片描述

4)初始化一個類的子類

  • 子類調用父類的靜態方法,父類初始化,子類並不會被初始化
    在這裏插入圖片描述
  • 子類調用自己的靜態變量纔會被初始化
    在這裏插入圖片描述

5)JVM啓動時被標記爲啓動類的類

在這裏插入圖片描述

6)MethodHandle【空】

4、常量與類的初始化

4.1)編譯期能確定常量

  • 在編譯階段會存入調用這個常量的方法的類的常量池中
  • 本質上,調用類,並沒有直接引用到定義類的常量,因此,不會初始化定義常量的類
  • 即:A中aa存放到testAB的常量池中

    示例

    在這裏插入圖片描述

    測試 -------刪除A的字節碼

在這裏插入圖片描述

反編譯:

  • 補充:還有iconst_0,iconst_m1(minus1/-1)
    在這裏插入圖片描述
    在這裏插入圖片描述

常量aa=100時,變bipush

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

  • 另:反編譯的用法:
    在這裏插入圖片描述

4.2)當常量值在運行期才能確定時

在這裏插入圖片描述

  • 刪除定義常量的類的字節碼文件
    在這裏插入圖片描述

證明:當一個常量的值在編譯期無法確定運行期才能確定時,它不會被放到調用此常量的類的常量池中,而是主動使用此常量被定義的類(定義此常量的類會被初始化)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章