JVM 切入點-Hellow word 會當凌絕頂、一覽衆山小 前端編譯與優化

JVM讀書總結

切入點-Hellow word

學習中知識點很多逐個記概念很容易忘記,要找到切入點通過這個切入點生根,然後形成知識樹或叫知識體系,在從知識體系上延伸出很多的知識點,前後依賴。這樣就很容及記住某個知識點的來龍去脈。jvm的脈絡梳理需要找到一個切入點,然後將所有的知識點串聯起來。

剛學習java的時候,老師通過txt寫一段經典的程序Hellow word,經過了幾個步驟,安裝jdk、打開記事本編寫一段hellow word代碼保存爲Test.java、然後cmd 運行javac Test.java、再運行 java Test、然後控制檯就輸出了這段Hellow word。

以上雖然是一段最簡單的程序,但是對於java來說卻經歷了最全的幾個重要階段;

  1. 編碼階段

    源碼編寫階段,主要用到了jdk(Java Development Kit)中封裝好的api方法。

  2. 編譯階段

    本階段也稱之爲前端編譯階段,將編寫好的java源文件編譯成.class字節碼,主要用到jdk中的javac編譯器。

  3. 執行階段

    執行階段主要是靠jre(Java Runtime Environment)java運行時環境。jre分爲bin、lib兩個目錄,bin認爲就是jvm,lib是.class後綴的基本類庫。在運行我們的.class文件時需要依賴的。那麼執行階段就是jvm的重頭戲。

    那麼執行階段jvm都做的哪些事情,首先jvm需要將編譯好的.class字節碼加載運行時數據區,再通過執行引擎執行。

通過以上三個階段就能解決java第一個特性,Write Once,Run Anywhere。如圖;


還有一個特性就是內存自動管理,不需要開發人員操心對象應該分配多大內存(內存自動分配),和哪些內存需要回收(Garbage Collection)。如圖;

通過上面描述的Hellow word 就已經將這本書講到的jvm的核心知識點基本上都很清楚的(黑色加粗字體)羅列出來了,爲什麼把jdk和jre也標記出來的原因是有些牛逼(無腦)面試官會問,比如兩個的區別。通過一個示例的切入點整理出了jvm的知識體系枝幹,按照順序整理。

  • 前端編譯階段:雖然不屬於jvm負責的事,但是本書裏面也詳細提到了(第10章 前端編譯與優化),所以接下來也總結一下。

  • .class字節碼:class字節碼生成也不屬於jvm的事,歸jdk的javac編譯器。本書也詳細提到了(第6章 類文件結構),所以。

  • .class字節碼加載:這個屬於jvm的活,(第7章 虛擬機類加載機制)以及(第9章 類加載及執行子系統的案例與事件),講了一些有名的容器用到了類加載。

  • 運行時數據區:純jvm的活,也是面試重點。(第2章 內存區域與內存溢出)

  • 自動內存管理:純jvm的活,分爲內存自動分配、垃圾回收也是面試重點。(第3章 垃圾收集器與內存分配策略)以及一些調優實踐(第4章 虛擬機性能監控、故障處理工具)(第5章 調優案例分析與實踐)。

  • 執行引擎:純jvm的活,除了對虛擬機字節碼解釋執行外,還會對一些熱點邏輯做優化編譯爲本地機器碼。本書(第8章 虛擬機字節碼執行引擎)和(第11章 後端編譯與優化)以及(第9章 類加載及執行子系統的案例與事件)。看圖;

這就是個人理解的脈絡,按照這個脈絡再針對每個點詳細學習總結。本書最後一部分講到了高效併發,也是面試重地,最後總結。

會當凌絕頂、一覽衆山小

本書看了兩遍,第一遍從第二章看到結尾,第二遍從結尾看到第二章,第一遍很蒙,第二遍好點,但是腦海裏也僅僅停留着某個章節某些點很零散,借用本書的比喻就是一堆零散的點找不到根,分分中被幹掉真的記不住。當我開始總結這篇筆記的時候已經第三遍開始了。可能是因爲看兩遍之後纔有的感覺,找到切入點,捋清楚脈絡,俯視這些章節知識點的時候會感覺輕鬆很多,也不會那麼的牴觸,帶着問題讀書會更有效率吧。

這張圖就是站在山頂描繪的全貌,接下來的時間裏還是需要反覆讀本書,不斷總結不斷學習。最終目的不僅僅是爲了浮於表面只針對概念侃侃而談,而是真正的要能應用到實際應用中,去解決實際的問題。

前端編譯與優化

前端編譯是將各種語言(java、JRuby、Croovy等語言)變異成.class字節碼。

那麼java前端編譯指的就是javac,或者說是Eclipse JDT中的增量式編譯器(ECJ),ECJ具體不瞭解應該就是另一種java前端編譯器。以下描述的前端編譯只針對java,其他的不瞭解。

前端編譯期間除了將java文件編譯成爲了.class文件,同時也做了優化。這個優化只針對程序員開發效率層面的優化,比如java語法增加了很多語法糖前端優化負責解糖,讓開發人員在寫代碼的時候提高效率。而運行效率方面的優化不由前端編譯負責,而是由後端編譯負責。java這樣設計的原因是第二個夢想,希望不僅java語言能運行在jvm上,其他語言也可以運行在jvm上,只是前端編譯實現不同而生成的.class字節碼相同。

javac源碼與調試

javac源碼在 openjdk7/langtools/src/share/classes/com/sun/tools/javac中。到了jdk9以後整個jdk所有類庫都採用模塊化重構了/src/jdk.compiler/share/classes/com/sun/tools/javac。本書將的是jdk9之前。

javac編譯器除了jkd類庫外,就只引用了/langtools/src/share/classes/com/sun/*;裏面的代碼,所以通過Eclipse,先建立一個Compiler_javac的java工程,然後把從com以後的代碼都拷貝到工程src下面即可。


通過com.sun.tools.javac.Main 的 main()方法就可以執行了,編譯文件的參數在Run Configurations面板中的Arguments頁籤中指定


javac編譯過程

javac代碼編譯過程分爲1個準備過程和3個處理過程;

1)準備過程:初始化插入式註解處理器。

2)解析與填充符號表過程,包括:

  • 詞法、語法分析。將源代碼的字符流轉變爲標記集合,構造出抽象語法樹。

  • 填充符號表。產生符號地址和符號信息。

3)插入式註解處理器的註解處理過程:插入式註解處理器的執行階段。

4)分析與字節碼生成過程,包括:

  • 標註檢查。對語法的靜態信息進行檢查。

  • 數據流及控制流分析。對程序動態運行過程進行檢查。

  • 解語法糖。將簡化代碼編寫的語法糖還原爲原有的形式(拆裝箱、泛型擦除、變長參數)。

  • 字節碼生成。將前面各個步驟所生成的信息轉化成字節碼。

插入式註解是開發人員可以干預的。通過繼承AbstractProcessor處理編譯期間對抽象語法樹修改。

解析與填充符號表

1.詞法、語法分析

詞法分析是將源代碼的字符流轉變爲標記集合,構造抽象語法樹。單個字符是程序編寫時的最小元素,而標記則是編譯時的最小元素,關鍵字、變量名、字面量、運算符都是標記;int a = b + 2 這句代碼就6個標記。javac源碼中,詞法分析過程由com.sun.tools.javac.parser.Scanner類實現。

語法分析是根據標記序列構造抽象語法樹的過程

Lombok原理分析與功能實現 (mythsman.com)

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