內容提要
《揭秘Java虛擬機:JVM設計原理與實現》從源碼角度解讀HotSpot的內部實現機制,本版本主要包含三大部分——JVM數據結構設計與實現、執行引擎機制及記憶體分配模型。
數據結構部分包括Java位元組碼檔案格式、常量池解析、欄位解析、方法解析。每一部分都給出詳細的源碼實現分析,例如欄位解析一章,從源碼層面詳細分析了Java欄位重排、欄位繼承等關鍵機制。再如方法解析一章,給出了Java多態特性在源碼層面的實現方式。《揭秘Java虛擬機:JVM設計原理與實現》通過直接對原始碼的分析,從根本上梳理和澄清Java領域中的關鍵概念和機制。
執行引擎部分包括Java方法調用機制、棧幀創建機制、指令集架構與解釋器實現機制。這一話題是《揭秘Java虛擬機:JVM設計原理與實現》技術含量最高的部分,需要讀者具備一定的彙編基礎。不過千萬不要被“彙編”這個詞給嚇著,其實在作者看來,彙編相比於高級語言而言,語法非常簡單,語義也十分清晰。執行引擎部分重點描述Java原始碼如何轉換為位元組碼,又如何從位元組碼轉換為機器指令從而能夠被物理CPU所執行的技術實現。同時詳細分析了Java函式堆疊的創建全過程,在源碼分析的過程中,帶領讀者從本質上理解到底什麼是Java函式堆疊和棧幀,以及棧幀內部的詳細結構。
記憶體分配部分主要包括類型創建與載入、對象實例創建與記憶體分配,例如new關鍵字的工作機制,import關鍵字的作用,再如java.lang.ClassLoader.loadClass()接口的本地實現機制。
《揭秘Java虛擬機:JVM設計原理與實現》並不是簡單地分析源碼實現,而是在描述HotSpot內部實現機制的同時,分析了HotSpot如此這般實現的技術必然性。讀者在閱讀《揭秘Java虛擬機:JVM設計原理與實現》的過程中,將會在很多地方看到作者本人的這種思考。
目錄
第1 章 Java 虛擬機概述 1
1.1 從機器語言到Java——詹爺,你好 1
1.2 兼容的選擇:一場生產力的革命 6
1.3 中間語言翻譯 10
1.3.1 從中間語言翻譯到機器碼 11
1.3.2 通過C 程式翻譯 11
1.3.3 直接翻譯為機器碼 13
1.3.4 本地編譯 16
1.4 神奇的指令 18
1.4.1 常見彙編指令 20
1.4.2 JVM 指令 21
1.5 本章總結 24
第2 章 Java 執行引擎工作原理:方法調用 25
2.1 方法調用 26
2.1.1 真實的機器調用 26
2.1.2 C 語言函式調用 41
2.2 JVM 的函式調用機制 47
2.3 函式指針 53
2.4 CallStub 函式指針定義 60
2.5 _call_stub_entry 例程 72
2.6 本章總結 114
第3 章 Java 數據結構與面向對象 115
3.1 從Java 算法到數據結構 116
3.2 數據類型簡史 120
3.3 Java 數據結構之偶然性 127
3.4 Java 類型識別 130
3.4.1 class 位元組碼概述 131
3.4.2 魔數與JVM 內部的int 類型 134
3.4.3 常量池與JVM 內部對象模型 135
3.5 大端與小端 141
3.5.1 大端和小端的概念 144
3.5.2 大小端產生的本質原因 146
3.5.3 大小端驗證 147
3.5.4 大端和小端產生的場景 149
3.5.5 如何解決位元組序反轉 152
3.5.6 大小端問題的避免 154
3.5.7 JVM 對位元組碼檔案的大小端處理 154
3.6 本章總結 157
第4 章 Java 位元組碼實戰 158
4.1 位元組碼格式初探 158
4.1.1 準備測試用例 159
4.1.2 使用javap 命令分析位元組碼檔案 159
4.1.3 查看位元組碼二進制 162
4.2 魔數與版本 163
4.2.1 魔數 165
4.2.2 版本號 165
4.3 常量池 166
4.3.1 常量池的基本結構 166
4.3.2 JVM 所定義的11 種常量 167
4.3.3 常量池元素的複合結構 167
4.3.4 常量池的結束位置 169
4.3.5 常量池元素總數量 169
4.3.6 第一個常量池元素 170
4.3.7 第二個常量池元素 171
4.3.8 父類常量 171
4.3.9 變數型常量池元素 172
4.4 訪問標識與繼承信息 174
4.4.1 access_flags 174
4.4.2 this_class 175
4.4.3 super_class 176
4.4.4 interface 177
4.5 欄位信息 177
4.5.1 fields_count 177
4.5.2 field_info fields[fields_count] 178
4.6 方法信息 182
4.6.1 methods_count 182
4.6.2 method_info methods[methods_count] 183
4.7 本章回顧 203
第5 章 常量池解析 204
5.1 常量池記憶體分配 206
5.1.1 常量池記憶體分配總體鏈路 207
5.1.2 記憶體分配 212
5.1.3 初始化記憶體 221
5.2 oop-klass 模型 222
5.2.1 兩模型三維度 223
5.2.2 體系總覽 224
5.2.3 oop 體系 226
5.2.4 klass 體系 229
5.2.5 handle 體系 232
5.2.6 oop、klass、handle 的相互轉換 237
5.3 常量池klass 模型(1) 242
5.3.1 klassKlass 實例構建總鏈路 244
5.3.2 為klassOop 申請記憶體 248
5.3.3 klassOop 記憶體清零 251
5.3.4 初始化mark 251
5.3.5 初始化klassOop._metadata 256
5.3.6 初始化klass 257
5.3.7 自指 258
5.4 常量池klass 模型(2) 258
5.4.1 constantPoolKlass 模型構建 258
5.4.2 constantPoolOop 與klass 261
5.4.3 klassKlass 終結符 264
5.5 常量池解析 264
5.5.1 constantPoolOop 域初始化 264
5.5.2 初始化tag 266
5.5.3 解析常量池元素 267
5.6 本章總結 276
第6 章 類變數解析 277
6.1 類變數解析 278
6.2 偏移量 282
6.2.1 靜態變數偏移量 282
6.2.2 非靜態變數偏移量 284
6.2.3 Java 欄位記憶體分配總結 309
6.3 從源碼看欄位繼承 315
6.3.1 欄位重排與補白 316
6.3.2 private 欄位可被繼承嗎 322
6.3.3 使用HSDB 驗證欄位分配與繼承 325
6.3.4 引用類型變數記憶體分配 333
6.4 本章總結 338
第7 章 Java 棧幀 340
7.1 entry_point 例程生成 341
7.2 局部變數表創建 349
7.2.1 constMethod 的記憶體布局 349
7.2.2 局部變數表空間計算 352
7.2.3 初始化局部變數區 355
7.3 堆疊與棧幀 364
7.3.1 棧幀是什麼 364
7.3.2 硬體對堆疊的支持 383
7.3.3 棧幀開闢與回收 386
7.3.4 堆疊大小與多執行緒 388
7.4 JVM 的棧幀 392
7.4.1 JVM 棧幀與大小確定 392
7.4.2 棧幀創建 396
7.4.3 局部變數表 418
7.5 棧幀深度與slot 復用 430
7.6 最大運算元棧與操作棧復用 433
7.7 本章總結 436
第8 章 類方法解析 437
8.1 方法簽名解析與校驗 442
8.2 方法屬性解析 444
8.2.1 code 屬性解析 444
8.2.2 LVT&LVTT 446
8.3 創建methodOop 452
8.4 Java 方法屬性複製 456
8.5 <clinit>與<init> 458
8.6 查看運行時位元組碼指令 479
8.7 vtable 486
8.7.1 多態 486
8.7.2 C++中的多態與vtable 488
8.7.3 Java 中的多態實現機制 490
8.7.4 vtable 與invokevirtual 指令 497
8.7.5 HSDB 查看運行時vtable 499
8.7.6 miranda 方法 502
8.7.7 vtable 特點總結 505
8.7.8 vtable 機制邏輯驗證 506
8.8 本章總結 508
第9 章 執行引擎 510
9.1 執行引擎概述 511
9.2 取指 513
9.2.1 指令長度 516
9.2.2 JVM 的兩級取指機制 524
9.2.3 取指指令放在哪 529
9.2.4 程式計數器在哪裡 531
9.3 解碼 532
9.3.1 模板表 532
9.3.2 彙編器 538
9.3.3 彙編 546
9.4 棧頂快取 555
9.5 棧式指令集 563
9.6 運算元棧在哪裡 574
9.7 棧幀重疊 578
9.8 entry_point 例程機器指令 583
9.9 執行引擎實戰 585
9.9.1 一個簡單的例子 585
9.9.2 位元組碼運行過程分析 587
9.10 位元組碼指令實現 594
9.10.1 iconst_3 594
9.10.2 istore_0 596
9.10.3 iadd 597
9.11 本章總結 598
第10 章 類的生命周期 599
10.1 類的生命周期概述 599
10.2 類載入 602
10.2.1 類載入——鏡像類與靜態欄位 609
10.2.2 Java 主類載入機制 614
10.2.3 類載入器的載入機制 620
10.2.4 反射載入機制 621
10.2.5 import 與new 指令 622
10.3 類的初始化 623
10.4 類載入器 626
10.4.1 類載入器的定義. 626
10.4.2 系統類載入器與擴展類載入器創建 632
10.4.3 雙親委派機制與破壞 634
10.4.4 預載入 636
10.4.5 引導類載入 638
10.4.6 載入、連結與延遲載入 639
10.4.7 父載入器 643
10.4.8 載入器與類型轉換 646
10.5 類實例分配 647
10.5.1 棧上分配與逃逸分析 650
10.5.2 TLAB 654
10.5.3 指針碰撞與eden 區分配 655
10.5.4 清零 656
10.5.5 偏向鎖 657
10.5.6 壓棧與取指 658
10.6 本章總結 660