目錄
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)當常量值在運行期才能確定時
- 刪除定義常量的類的字節碼文件