1.概述
Java虛擬機機制(JVM)
“書寫一次,到處運行”, 能夠非常容易獲得跨平臺能力. Java 通過字節碼和 Java 虛擬機(JVM)這種跨平臺的抽象,屏蔽了操作系統和硬件的細節,這也是實現“一次編譯,到處執行”的基礎。
流程: 源代碼(.java文件) -> 編譯 -> 字節碼(.class文件) -> 執行(不同平臺的JVM)
- 類加載大致過程:加載、驗證、鏈接、初始化(這裏參考了周志明的《深入理解 Java 虛擬機》 ,非常棒的 JVM 上手書籍)
垃圾回收機制(GC)
- 提供了一種系統級線程跟蹤存儲空間的分配情況,並在JVM的空閒時釋放那些可以被釋放的存儲器的空間。
- 垃圾回收是在java程序運行過程中自動進行的,程序員無法精準控制和干預。
JRE和JDK
- JRE就是 Java 運行環境,包含了 JVM 和 Java 類庫,以及一些模塊等。
- JDK可以看作是 JRE 的一個超集,提供了更多工具,比如編譯器、各種診斷工具等。
java語言特性
- 泛型、Lambda 等
基礎類庫
- 集合、IO/NIO、網絡、併發、安全等基礎類庫
三大特徵
- 封裝,繼承,多態
Java藍圖
2.Java的編譯執行
java是解釋型語言
- 我們開發的 Java 的源代碼,首先通過 Javac 編譯成爲字節碼(bytecode),然後,在運行時,通過 Java 虛擬機(JVM)內嵌的解釋器將字節碼轉換成爲最終的機器碼。但是常見的 JVM,比如我們大多數情況使用的 Oracle JDK 提供的 Hotspot JVM,都提供了 JIT(Just-In-Time)編譯器,也就是通常所說的動態編譯器,JIT 能夠在運行時將熱點代碼編譯成機器碼,這種情況下部分熱點代碼就屬於編譯執行,而不是解釋執行了。
- Java 分爲編譯期和運行時 : ①Javac 的編譯,編譯 Java 源碼生成“.class”文件裏面實際是字節碼,而不是可以直接執行的機器碼。Java 通過字節碼和 Java 虛擬機(JVM)這種跨平臺的抽象,屏蔽了操作系統和硬件的細節,這也是實現“一次編譯,到處執行”的基礎。②在運行時,JVM 會通過類加載器(Class-Loader)加載字節碼,解釋或者編譯執行。
java編譯方式
- 主流 Java 版本中,如 JDK 8 實際是解釋和編譯混合的一種模式,即所謂的混合模式(-Xmixed)。通常運行在 server 模式的 JVM,會進行上萬次調用以收集足夠的信息進行高效的編譯,client 模式這個門限是 1500 次。Oracle Hotspot JVM 內置了兩個不同的 JIT compiler,C1 對應前面說的 client 模式,適用於對於啓動速度敏感的應用,比如普通 Java 桌面應用;C2 對應 server 模式,它的優化是爲長時間運行的服務器端應用設計的。默認是採用所謂的 分層編譯(TieredCompilation) 。
- Java 虛擬機啓動時,可以指定不同的參數對運行模式進行選擇。 比如,指定“-Xint”,就是告訴 JVM 只進行解釋執行,不對代碼進行編譯,這種模式拋棄了 JIT 可能帶來的性能優勢。畢竟解釋器(interpreter)是逐條讀入,逐條解釋運行的。與其相對應的,還有一個“-Xcomp”參數,這是告訴 JVM 關閉解釋器,不要進行解釋執行,或者叫作最大優化級別。-Xcomp”會導致 JVM 啓動變慢非常多,同時有些 JIT 編譯器優化方式,比如分支預測,如果不進行 profiling,往往並不能進行有效優化。
- 除了我們日常最常見的 Java 使用模式,其實還有一種新的編譯方式,即所謂的 AOT(Ahead-of-Time Compilation),直接將字節碼編譯成機器代碼,這樣就避免了 JIT 預熱等各方面的開銷,比如 Oracle JDK 9 就引入了實驗性的 AOT 特性,並且增加了新的 jaotc 工具。利用下面的命令把某個類或者某個模塊編譯成爲 AOT 庫:
jaotc --output libHelloWorld.so HelloWorld.class
jaotc --output libjava.base.so --module java.base
然後,在啓動時直接指定就可以了。
java -XX:AOTLibrary=./libHelloWorld.so,./libjava.base.so HelloWorld
而且,Oracle JDK 支持分層編譯和 AOT 協作使用,這兩者並不是二選一的關係。