內建的JIT編譯器、日漸成熟的垃圾收集器(多線程化)、不斷改進的運行時環境(JVM Runtime Environment)。java
HotSpot VM組件瀏覽器
VM運行時(Runtime)、JIT編譯器(JIT Compiler)、內存管理器(Memory Manager)。緩存
HotSpot VM的基本架構安全
HotSpot VM架構功能強大,能夠知足高性能和高擴展性。支持HotSpot VM JIT編譯器的動態優化,能夠在Java應用運行時制定優化策略,並依據底層系統架構生成高效的本地機器指令。網絡
JIT編譯器(Client或Server)和垃圾收集器(Serial、Throughput、CMS或G1)都是可插拔的。
HotSpot VM運行時系統爲HotSpot JIT編譯器和垃圾收集器提供服務和通用API。還爲VM提供啓動、線程管理、JNI(Java本地接口)等基本功能。數據結構
早期的HotSpot VM(32位JVM)多線程
早期的HotSpot VM是32位JVM,內存地址空間限制爲4G,關鍵的是,實際Java堆的大小還進一步受限於底層操做系統。
Windows系統上HotSpot VM最大可用的Java堆大約爲1.5G。
HotSpot VM在最新Linux內核上的最大可用Java堆大約爲2.5G到3.0G。在較早內核版本上大約爲2G。
Solaris上HotSpot VM最大可用的Java堆大約爲3.3G。架構
實際消耗的最大內存地址空間隨給定的Java應用和JVM版本而有所不一樣。app
64位HotSpot VMoop
增大了Java堆,使得這些系統可使用更多內存。
64位HotSpot VM——性能損失——壓縮指針
HotSpot VM內部Java對象表示(普通對象指針,Ordinary Object Pointers,oops)長度從32位變爲64位,致使CPU高速緩存行中可用的普通對象指針變少,從而下降了CPU緩存的效率。緩存效率的下降致使性能比32位JVM下降8%~15%。
最新的Java 6 HotSpot VM添加了壓縮指針(Compressed oops,-XX:+UseCompressedOops開啓)的新特性,使得64位Java的大尺寸堆和32位JVM的性能能夠兼得。
一些Java應用在64位HotSpot VM上使用壓縮指針以後,性能要好於32位VM。
64位HotSpot VM——性能提升緣由
64位JVM可使用更多的CPU寄存器,這有助於程序性能的改善。更多的CPU寄存器能夠避免寄存器卸載。當活躍狀態數超過CPU寄存器數,多出的活躍狀態只能存放在內存中時,就會發生寄存器卸載。寄存器卸載時,某些活躍狀態必須從CPU寄存器卸載到內存中,所以避免寄存器卸載可讓程序執行得更快。
壓縮指針改善性能的緣由
經過對齊、偏移量(Offset)將64位指針壓縮成32位。
性能提升是由於使用了更小更節省空間的壓縮指針而不是完整長度的64位指針,CPU緩存使用率由此獲得改善。
HotSpot VM運行時責任
HotSpot VM運行時環境責任:命令行選項解析、VM生命週期管理、類加載、字節碼解釋、異常處理、同步、線程管理、Java本地接口、VM致命錯誤處理、C++(非Java)堆管理。
HotSpot VM運行時——命令行選項——使用的對象——啓動器和HotSpot VM
命令行選項
HotSpot VM啓動器使用(指定選擇哪一個JIT編譯器、選擇何種垃圾收集器)
經啓動器處理後傳給完成啓動的HotSpot VM。
HotSpot VM運行時——命令行選項——類別
標準選項(Standard Option)
非標準選項(Nonstandard Option)
非穩定選項(Developer Option)
HotSpot VM運行時——命令行選項——標準選項
Java Virtual Machine Specification要求全部Java虛擬機都必須實現的選項,它們在發行版之間保持穩定,但也可能在後續的發行版中被廢除。
HotSpot VM運行時——命令行選項——非標準選項(以-X
爲前綴)
不保證、也不強制全部JVM實現都必須支持,它可能未經通知就在Java SDK發行版之間發生更改。
HotSpot VM運行時——命令行選項——非穩定選項(以-XX爲前綴)
爲了特定須要而對JVM的運行進行校訂,而且可能須要有系統配置參數的訪問權限。
非穩定選項也可能不經通知就在發行版之間發生變更。
HotSpot VM運行時——命令行選項——布爾類型的選項
命令行選項用於控制HotSpot VM的內部變量,每一個變量都有類型和默認值。
對於內部變量爲布爾類型的選項來講,只要在HotSpot VM命令行上添加或去掉就能夠控制這些變量。
對於帶有布爾標記的非穩定選項來講,選項名前的+或-表示true或false,用於開啓或關閉特定的HotSpot VM特性或參數。
HotSpot VM運行時——VM生命週期——啓動器
HotSpot VM運行時系統負責啓動和中止HotSpot VM。
啓動HotSpot VM的組件是啓動器:
Unix/Linux: java
Windows:java和javaw
JNI接口:JNI_CreateJavaVM啓動內嵌的JVM
網絡啓動器:javaws(Java Web Start),Web瀏覽器用它來啓動applet。
HotSpot VM運行時——VM生命週期——啓動器啓動HotSpot VM步驟
(1)解析命令行選項
啓動器會直接處理一些命令行選項,例如-client
或-server
,它們決定加載那個JIT編譯器,其餘參數則傳給HotSpot VM。
(2)設置堆的大小和JIT編譯器。
若是命令行沒有明確設置堆的大小和JIT編譯器(client或server),啓動器則經過自動優化進行設置。自動優化的默認設定因底層系統配置和操做系統而有所不一樣。
(3)設定環境變量如LD_LIBRARY_PATH。
(4)若是命令行有-jar
選項,啓動器則從指定JAR的manifest
中查找Main-Class,不然從命令行讀取Main-Class。
(5)使用標準Java本地接口(Java Native Interface,JNI)方法JNI_CreateJavaVM在新建立的線程中建立HotSpot VM。
與後建立的線程相比,初始線程是啓動新進程時操做系統內核分配的第一個線程。
不在初始線程中建立HotSpot VM,是爲了能夠對它進行定製。
(6)一旦建立並初始化好HotSpot VM,就會加載Java Main-Class,啓動器也會從Java Main-Class中獲得Java main方法的參數。
(7)HotSpot VM經過JNI方法CallStaticVoidMethod
調用Java Main方法,並將命令行選項傳給它。
至此,HotSpot VM開始正式執行命令行指定的Java程序了。
一旦Java程序或Java Main方法執行結束,HotSpot VM就必須檢查和清理全部程序或者方法執行過程當中生成的未處理異常。此外,方法的退出狀態和程序的退出狀態也必須返回給它們的調用者。
調用Java本地接口方法DetachCurrentThread
將Java main方法與HotSpot VM脫離(Detached)。每次HotSpot VM調用時,線程數就會減1,所以Java本地接口知道什麼時候能夠安全地關閉HotSpot VM,並能確保當時HotSpot VM中沒有正在執行的操做,Java棧中也沒有激活的Java幀。
JNI_CreateJavaVM詳解
(1)確保只有一個線程調用這個方法而且確保只建立一個HotSpot VM實例。HotSpot VM建立的靜態數據結構沒法再次初始化,因此一旦初始到達到某個肯定點後,進程空間裏就只能有一個HotSpot VM。HotSpot VM啓動至此已是沒法逆轉了。(2)檢查並確保支持當前的JNI版本,初始化垃圾收集日誌的輸出流。(3)初始化OS模塊,如隨機數生成器,當前進程id、高精度計時器、內存頁尺寸、保護頁。保護也是不可訪問的內存頁,用作內存訪問區域的邊界。例如操做系統常在線程棧頂壓入一個保護頁以保證引用不會超出棧的邊界。(4)解析傳入JNI_CreateJavaVM的命令行選項,保存以備未來使用。(5)初始化標準的Java系統屬性,例如java.version、java.vendor、os.name等。(6)初始化支持同步、棧、內存和安全點頁的模塊。(7)加載libzip、libhpi、libjava及libthread等庫。(8)初始化並設置信號處理器(Signal Handler)。(9)初始化線程庫。(10)初始化輸出流日誌記錄器(Logger)。(11)若是用到Agent庫(hprof、jdi),則初始化並啓動。(12)初始化線程狀態(Thread State)和線程本地存儲(Thread Local Storage),它們存儲了線程私有數據。(13)初始化部分HotSpot VM全局數據,例如事件日誌(Event Log),OS同步原語、perfMemory(性能統計數據內存),以及chunkPool(內存分配器)。(14)至此,HotSpot VM能夠建立線程了。建立出來的Java版main線程被關聯到當前操做系統的線程,只不過尚未添加到已知線程列表中。(15)初始化並激活Java級別的同步。(16)初始化啓動類加載器(Bootclassloader)、代碼緩存、解釋器、JIT編譯器、JNI、系統詞典(System Dictionary)及universe(一種必備的全局數據結構集)。(17)如今,添加Java主線程到已知線程列表中。檢查universe是否正常。建立HotSpot VMThread,它執行HotSpot VM全部的關鍵功能。同時發出適當的JVMTI事件,報告HotSpot VM的當前狀態。(18)加載和初始化如下Java類:java.lang.String、java.lang.System、java.lang.Thread、java.lang.ThreadGroup、java.lang.reflect.Method、java.lang.ref.Finalizer、java.lang.Class以及餘下的Java系統類。此時,HotSpot已經初始化完畢並可以使用,只是功能還不完備。(19)啓動HotSpot VM的信號處理線程,初始化JIT編譯器並啓動HotSpot編譯代理線程。啓動HotSpot VM輔助線程(如監控線程和統計抽樣器)。至此,HotSpot VM已功能完備。(20)最後,生成JNIEnv對象返回給調用者,HotSpot則準備響應新的JNI請求。