揭秘Java虛擬機:JVM設計原理與實現( 簡體 字) | |
作者:封亞飛 | 類別:1. -> 程式設計 -> JAVA -> Java |
出版社:電子工業出版社 | 3dWoo書號: 47186 詢問書籍請說出此書號! 有庫存 NT售價: 645 元 |
出版日:6/1/2017 | |
頁數:700 | |
光碟數:0 | |
站長推薦: | |
印刷:黑白印刷 | 語系: ( 簡體 字 ) |
ISBN:9787121315411 | 加入購物車 │加到我的最愛 (請先登入會員) |
(簡體書上所述之下載連結耗時費功, 恕不適用在台灣, 若讀者需要請自行嘗試, 恕不保證, 繁體書的下載亦請直接連絡出版社) | |
第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 本章總結 115 第3章 Java數據結構與面向對象 117 3.1 從Java算法到數據結構 118 3.2 數據類型簡史 122 3.3 Java數據結構之偶然性 129 3.4 Java類型識別 132 3.4.1 class字節碼概述 133 3.4.2 魔數與JVM內部的int類型 136 3.4.3 常量池與JVM內部對象模型 137 3.5 大端與小端 143 3.5.1 大端和小端的概念 146 3.5.2 大小端產生的本質原因 148 3.5.3 大小端驗證 149 3.5.4 大端和小端產生的場景 151 3.5.5 如何解決字節序反轉 154 3.5.6 大小端問題的避免 156 3.5.7 JVM對字節碼文件的大小端處理 156 3.6 本章總結 159 第4章 Java字節碼實戰 161 4.1 字節碼格式初探 161 4.1.1 準備測試用例 162 4.1.2 使用javap命令分析字節碼文件 162 4.1.3 查看字節碼二進制 165 4.2 魔數與版本 166 4.2.1 魔數 168 4.2.2 版本號 168 4.3 常量池 169 4.3.1 常量池的基本結構 169 4.3.2 JVM所定義的11種常量 170 4.3.3 常量池元素的復合結構 170 4.3.4 常量池的結束位置 172 4.3.5 常量池元素總數量 172 4.3.6 第一個常量池元素 173 4.3.7 第二個常量池元素 174 4.3.8 父類常量 174 4.3.9 變量型常量池元素 175 4.4 訪問標識與繼承信息 177 4.4.1 access_flags 177 4.4.2 this_class 178 4.4.3 super_class 179 4.4.4 interface 179 4.5 字段信息 180 4.5.1 fields_count 180 4.5.2 field_info fields[fields_count] 181 4.6 方法信息 185 4.6.1 methods_count 185 4.6.2 method_info methods[methods_count] 185 4.7 本章回顧 205 第5章 常量池解析 206 5.1 常量池內存分配 208 5.1.1 常量池內存分配總體鏈路 209 5.1.2 內存分配 215 5.1.3 初始化內存 223 5.2 oop-klass模型 224 5.2.1 兩模型三維度 225 5.2.2 體系總覽 227 5.2.3 oop體系 229 5.2.4 klass體系 231 5.2.5 handle體系 234 5.2.6 oop、klass、handle的相互轉換 239 5.3 常量池klass模型(1) 244 5.3.1 klassKlass實例構建總鏈路 246 5.3.2 為klassOop申請內存 249 5.3.3 klassOop內存清零 253 5.3.4 初始化mark 253 5.3.5 初始化klassOop._metadata 258 5.3.6 初始化klass 259 5.3.7 自指 260 5.4 常量池klass模型(2) 261 5.4.1 constantPoolKlass模型構建 261 5.4.2 constantPoolOop與klass 264 5.4.3 klassKlass終結符 267 5.5 常量池解析 267 5.5.1 constantPoolOop域初始化 268 5.5.2 初始化tag 269 5.5.3 解析常量池元素 271 5.6 本章總結 279 第6章 類變量解析 280 6.1 類變量解析 281 6.2 偏移量 285 6.2.1 靜態變量偏移量 285 6.2.2 非靜態變量偏移量 287 6.2.3 Java字段內存分配總結 312 6.3 從源碼看字段繼承 319 6.3.1 字段重排與補白 319 6.3.2 private字段可被繼承嗎 325 6.3.3 使用HSDB驗證字段分配與繼承 329 6.3.4 引用類型變量內存分配 338 6.4 本章總結 342 第7章 Java棧幀 344 7.1 entry_point例程生成 345 7.2 局部變量表創建 352 7.2.1 constMethod的內存布局 352 7.2.2 局部變量表空間計算 356 7.2.3 初始化局部變量區 359 7.3 堆棧與棧幀 368 7.3.1 棧幀是什么 368 7.3.2 硬件對堆棧的支持 387 7.3.3 棧幀開辟與回收 390 7.3.4 堆棧大小與多線程 391 7.4 JVM的棧幀 396 7.4.1 JVM棧幀與大小確定 396 7.4.2 棧幀創建 399 7.4.3 局部變量表 421 7.5 棧幀深度與slot復用 433 7.6 最大操作數棧與操作數棧復用 436 7.7 本章總結 439 第8章 類方法解析 440 8.1 方法簽名解析與校驗 445 8.2 方法屬性解析 447 8.2.1 code屬性解析 447 8.2.2 LVT&LVTT 449 8.3 創建methodOop 455 8.4 Java方法屬性復制 459 8.5 <clinit>與<init> 461 8.6 查看運行時字節碼指令 482 8.7 vtable 489 8.7.1 多態 489 8.7.2 C++中的多態與vtable 491 8.7.3 Java中的多態實現機制 493 8.7.4 vtable與invokevirtual指令 500 8.7.5 HSDB查看運行時vtable 502 8.7.6 miranda方法 505 8.7.7 vtable特點總結 508 8.7.8 vtable機制邏輯驗證 509 8.8 本章總結 511 第9章 執行引擎 513 9.1 執行引擎概述 514 9.2 取指 516 9.2.1 指令長度 519 9.2.2 JVM的兩級取指機制 527 9.2.3 取指指令放在哪 532 9.2.4 程序計數器在哪里 534 9.3 譯碼 535 9.3.1 模板表 535 9.3.2 匯編器 540 9.3.3 匯編 549 9.4 棧頂緩存 558 9.5 棧式指令集 565 9.6 操作數棧在哪里 576 9.7 棧幀重疊 581 9.8 entry_point例程機器指令 586 9.9 執行引擎實戰 588 9.9.1 一個簡單的例子 588 9.9.2 字節碼運行過程分析 590 9.10 字節碼指令實現 597 9.10.1 iconst_3 598 9.10.2 istore_0 599 9.10.3 iadd 600 9.11 本章總結 601 第10章 類的生命周期 602 10.1 類的生命周期概述 602 10.2 類加載 605 10.2.1 類加載——鏡像類與靜態字段 611 10.2.2 Java主類加載機制 617 10.2.3 類加載器的加載機制 622 10.2.4 反射加載機制 623 10.2.5 import與new指令 624 10.3 類的初始化 625 10.4 類加載器 628 10.4.1 類加載器的定義 628 10.4.2 系統類加載器與擴展類加載器創建 634 10.4.3 雙親委派機制與破壞 636 10.4.4 預加載 638 10.4.5 引導類加載 640 10.4.6 加載、鏈接與延遲加載 641 10.4.7 父加載器 645 10.4.8 加載器與類型轉換 648 10.5 類實例分配 649 10.5.1 棧上分配與逃逸分析 652 10.5.2 TLAB 655 10.5.3 指針碰撞與eden區分配 657 10.5.4 清零 658 10.5.5 偏向鎖 658 10.5.6 壓棧與取指 659 10.6 本章總結 661 《揭秘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設計原理與實現》的過程中,將會在很多地方看到作者本人的這種思考。
推薦序
從Java誕生至今已有二十余年,基于虛擬機的技術屏蔽了底層環境的差異,“一次編譯,隨處運行”的思想促進了整個IT上層技術應用產生了翻天覆地的變化。Java作為服務端應用語言的首選,確實大大降低了學習和應用的門檻。現實生活中,絕大多數Java程序員對于虛擬機的原理和實現了解并不深入,也似乎并不那么關心。而隨著互聯網的極速發展,現在的Java服務端應用需要應對極高的并發訪問和大量的數據交互,從機制和設計原理上了解虛擬機的核心原理和實現細節顯然能夠幫助Java程序員編寫出更高效優質的代碼。 雖然市面上從Java使用者角度介紹虛擬機的書也有不少佳作,但一般較為寬泛,尤其在談及虛擬機如何運行、處理的細節時總有些淺嘗輒止的遺憾。而作者憑借深厚的C與Java技術功底以及多年對于JVM的深入研究編寫的這本書,真正從虛擬機指令執行處理層面,結合JVM規范的設計原理,完整和詳盡地闡述了Java虛擬機在處理類、方法和代碼時的設計和實現細節。書中大量的代碼和指令細節能夠讓程序員更加直接地理解相關原理。 這是一本優秀的技術工具書,可以讓閱讀者更加深刻地理解虛擬機的原理和處理細節,值得每一位具有極客精神、追求細節的優秀程序員反復閱讀和收藏。 ——菜鳥平臺技術部 陌銘 前言 文明需要創造,也需要傳承。JVM作為一款虛擬機,本身便是技術之集大成者,里面包含方方面面的底層技術知識。拋開如今Java如日中天之態勢不說,純粹從技術層面看,JVM也值得廣大技術愛好者深入研究。可以說,從最新的硬件特性,到最新的軟件技術,只要技術被證明是成熟的,都會在JVM里面見到其蹤影。JDK的每一次更新,從內部到核心類庫,JVM都會及時引入這些最新的技術或者算法,這便是技術傳承意義之所在。隨著云計算、大數據、人工智能等最新技術的發展,Java技術生態圈也日益龐大,JVM與底層平臺以及與其他編程語言和技術的交互、交織日益深入,這些都離不開對JVM內部機制的深入理解。如果說以前在中間件與框架領域的大展身手,依靠的是Java語言層面的特性和技術,那么以后越來越多的技術紅利將會因JVM層面之創新而得以顯現。 被真相所蒙蔽,是一件痛苦的事。我們在一個被層層封裝的世界里進行開發和設計,操作系統、各種中間件與框架,將底層世界隱藏得結結實實。我們一方面享受著高級編程語言所帶來的高效、穩定、快速的開發體驗,然而另一方面,卻又如同行走于黑暗之中。我們不知道路的下面是否有坑,即使有坑,可能也不知道如何排除。Java的很多概念和技術,很多時候由于我們對底層機制的不了解,而讓我們感到十分高深莫測,無法知其全貌。這種感覺非常痛苦,尤其是技術修煉到一定階段的時候。 紙上得來終覺淺,絕知此事要躬行。即使從Java語言層面下探到JVM層面,但是若只囿于對JVM機制理論和概念上的理解,很多時候仍然覺得缺乏那種大徹大悟之感。計算機作為一門科學,與其他的科學領域一樣,不僅需要對其理論的理解,也需要能夠去實證。例如愛因斯坦的相對論十分高深,但是通過對引力波和紅移的觀測,其變得形象和生動起來。Java的部分概念經過“口口相傳”,似有過于夸大其技術神秘性之嫌,讓人望而生畏。例如,與volatile關鍵字相關的內存可見性、指令亂序等概念,給人無比博大深奧的印象,但是如能拋開概念,直接看底層實現機制,并輔以具體的實驗論證,則會形成深刻而徹底的認知。其實,這世界本來就很簡單。在可觀測的實驗結果與可理解的底層機制面前,一切浮夸的概念都自然會現出原形。 因此,采用自底而上的技術研究之道,相比自頂而下的辦法,便多了更多窺透本質的自信和平實。同一個底層概念,在不同的高級編程語言里,在概念、叫法上很少能夠保持一致。采用自底而上的探索方法,能夠揭開各種深奧概念的神秘面紗,還原一個清明簡潔的世界。自然理解曲線也不會有大起大落。 研究JVM的過程,就是與大師們進行精神溝通和心靈交流的過程,雖然過程會比較痛苦。研究諸如Linux、JVM這樣的底層程序,你能學習到大師級的理念,更能夠見識到經無數牛人反復錘煉后的技術。天長日久的耳濡目染,終有一天你也會成為大師,你也會擁有大師級的眼光,你也會擁有開闊的胸懷。如同音樂家李健,人們如此喜歡他,并不僅僅是因為他歌唱得好,更多的是因為氣質。而這種氣質來自于博覽群書,來自于對藝術的長久修煉。計算機從某種程度上而言,也是一門藝術,工程師和程序員們要想進化,對計算機藝術的修煉必不可少。與大師進行精神溝通,不僅能夠修煉到計算機的藝術,更能直接感受并養成大師身上所具備的氣質。 我不知道Java還能走多遠,未來是否會被淘汰,但你不能因此就否定研究JVM的意義。JVM作為一款虛擬機,各種底層技術和理論都有涉及,若你能研究透徹,則能一通百通。例如,本人在研究過程中,也翻閱了諸如Python、JavaScript等高級面向對象語言虛擬機的機制,發現它們內部的整體思路都相差不大。同時,JVM本身在運行期干了一部分C或C++語言編譯器所干的事,例如符號解析、鏈接、面向對象機制的實現等,通過對這些機制的分析,從來沒有研究過C/C++編譯器原理的我,基本也能夠猜出C/C++編譯器可能的實現方式,后來翻閱了相關資料,果不其然。理解編譯與虛擬機的實現機制是一方面,另一方面,通過深挖JDK核心類庫的內部實現,則能夠深刻理解線程、并發、I/O等比較高深的技術內幕。例如Java NIO,何謂VMA?何謂內核映射?若想真正徹底理解這些概念,不從底層入手,恐怕很難有一個具象化的認知。總之,研究JVM,是一件非常能夠提升開發者內功的事情,未來無論出現什么樣的新語言、新技術、新概念,你總是能夠不被表面的東西所迷惑,而是能夠透過層層封裝,看清事物的本質,你總是能夠以極低的學習成本,迅速理解新的東西。從一個更為廣闊的視角,使用發散的思維去看,不一定非要研究JVM才能有很大收獲,研究其他技術的底層,會有異曲同工之妙。而我只不過恰好生在了這個年代,這個Java語言大行其道的年代,所以就恰好對其做了一個比較深入的研究而已。工具有時空疆界,而技術思想則沒有,其總能穿越千萬年的時空,無限延伸。 JVM涉及的知識面十分廣闊,因此限于篇幅,本書并未覆蓋JVM的全部內容。總體而言,本書重點描述了JVM從啟動開始到完成函數執行的詳細機制,讀完本書,相信你一定能夠明白JVM執行Java程序的底層機制,能夠明白JVM將Java語言一步步轉換為CPU可執行的機器碼的內部機制,以及為此而制定的各種規范的實現之道,例如oop-klass模型、堆棧分配模型、類加載模型等。 本書作為筆者本人的處女作,前后寫了有兩年之久。之所以寫這么久,一方面是因為JVM本身涉及大量的知識,另一方面則是筆者本人在寫作過程中,力求對每一個知識點都做實驗進行驗證,避免因為筆者的錯誤理解而誤導了別人。同時,在這個過程中,筆者不僅僅滿足于讀懂JVM的源代碼,也不僅僅滿足于通過實驗去驗證各個技術點,筆者花了更多的時間在思考JVM各種技術選擇的必然性。換言之,在具體的硬件和操作系統的約束之下,在JVM“write once, run anywhere”這一思路設定下,JVM內部的技術實現機制是確定的,別無他法。例如,JVM的GC機制便是一種技術必然性選擇。每一次對這種技術必然性之思考,就好像與JVM的作者大牛們進行了一次心靈交流。 我問大牛:JVM的堆棧結構為什么要有操作數棧和局部變量表? 大牛回答:因為……。 大牛其實并沒有回答我,所有的一切都需要筆者自己去想明白。等想明白了之后,才有種真正看透事物本質的快感。 希望本書的讀者也能夠跟隨本書,一起去進行這樣的思考。 正是因為對“知其所以然”之追求,所以本書的寫作過程是漫長的。在此,要特別感謝我的老婆金艷和我的兒子佑佑,很多個周末我都沒能抽出時間陪伴他們。當我開始打算寫作本書時,我的孩子還在襁褓之中。而等我寫完本書,孩子已經開始上小班了。欠缺的太多! 在寫作本書的過程中,遇到了很多技術障礙,有很多技術障礙都是在查閱了R大以及阿里技術專家三紅、寒泉子等人的文章后才得以攻克,在此表示感謝!向這些大牛致敬! 同時,也要感謝我的領導和同事所給予的大力支持,尤其要感謝菲青、陌銘、祝幽、蘭博等人的鼓勵,同時你們也是我學習的榜樣! |