JVM基礎
什麼是JVM(Java Virtual Machine)?
直接引用《深刻Java虛擬機(原書第二版)》第五章的解釋:一、抽象規範;二、一個具體的實現;三、一個運行中的虛擬機實例。個人理解是:首先JVM是一份規範,由Sun公司制訂(如今是Oracle公司了),而後針對這個份 規範有多種實現版本,包括Sun和其它公司,運行在操做系統上面是一個具體的實例。數組
爲何要了解JVM?
若是是隻是簡單的實現增、刪、查、改功能或者作demo,確實不須要了解JVM。若是想進一步發掘Java性能、JVM調優、安全等知識,必須瞭解JVM。安全
JVM的架構?
引用網上圖片一張圖片,圖片源地址:https://dzone.com/articles/jvm-architecture-explained。圖片是JVM的邏輯圖,自上而下執行;注意順序和箭頭指向;簡單來講:由類型加載器子系統,運行時數據區,即時引擎組成。數據結構
Class Loader Subsystem(類裝載子系統)
類裝載器子系統除了定位和導入二進制Class文件外,還必須負責驗證被導入類的正確性,爲類變量分配並並初始化內存,以及幫助解析符號引用。類型包括:類和接口。類裝載子系統只識別Class文件,無論Class是怎麼生成和建立的。由於不只JAVA語言能夠建立Class文件,還有其它語言也能夠建立Class文件;其它語言建立的文件只要符合規範就能夠被JVM加載、鏈接、初始化;多線程
- 裝載,使用雙親委派的方式裝載類。根據Class路徑,查找到對應的Class文件,並導入二進制的Class數據。雙親委派的模式是Java保障安全的的一個重要方法,也是安全特性之一,能夠防止惡意代碼的被加載;裝載的最終產品就是這個Class類的實例對象;
- 鏈接,包括三個步驟:驗證、準備、解析。驗證:確保被導入類型的正確性。能夠理解爲確認類型符合Java語言的語義,而且不會危及虛擬機的完整性;根據必定規則驗證導入Class文件是否符合規範,Class文件的細節是否符合規範;準備:給類變量分配內存,並設置默認值;注意:這裏設置默認值是,Java類型的默認值,與代碼邏輯沒有關係(注意:這個階段不會執行Java代碼)。解析:類型的引用轉直接引用(因爲Java延遲機制,解析通會延遲到下一階段進行即:初始化)。
- 初始化:把類變量正確初始值。要執行JAVA代碼邏輯;
在這個裝載階段,有三個點須要搞明白:雙親委派模式、類加載器的命名空間、初始化(主動初始化、被動初始化)。這須要另起一篇文章才能講清楚,在這裏只提一下;架構
一個Class文件必須先被裝載後,才獲得類型的信息,類型的信息存儲於運行時的方法區中,即下面章節要介紹的內容;併發
Runtime Data Area(運行時數據區)
運行時數據區,包含:方法區、堆、棧、程序計數器、本地方法棧;你們即便對JVM不熟悉,也應該知道有堆的存在吧;下面咱們分別看下這些都是幹什麼的;jvm
- Method Area(方法區):經過Class Loader裝載後獲得的類型信息均存儲在方法區內,包括類型名稱、類型的超類、類型的接口、類型的訪問修飾符號、類型的常量池、字段信息、方法信息、方法字節碼、異常表、類(靜態)變量、編譯時常量(使用final以及編譯已知道的值初始化的類變量)等信息;實際是把Class文件映射爲JVM內部的數據結構,這樣JVM才使用執行Class文件邏輯;
- Heap Area(堆):Java運行時建立的類對象和數組均存儲在堆內;一個Java虛擬機實例只有一個堆,該虛擬機實現的全部線程共享堆空間。因爲一個Java程序獨佔一個Java虛擬機實例,因此每一個Java程序都有本身的堆空間;Java程序對於堆的操做是經過New關鍵去分配空間,但不能手動回收空間(System.gc只是建議JVM進行垃圾回收,何時執行由JVM決定);堆空間回收就是平時你們所理解的垃圾回收,但垃圾回收不只限於堆,也一樣適用於方法區;垃圾回收是一個很大課題,須要另起一篇介紹了;JVM的調優的重點也在堆分配和回收策略的制定;
- Stack Area(棧):啓動線程時,在棧區分配一個Java棧;局部變量和引用是存儲於線程棧,因此局部變量是不存在併發的問題;
- 程序計數器:Java程序中的每個線程的PC寄存器,是線程啓動時建立的;PC寄存器的大小是一個字長,內容老是線程下一條將被執行指令的"地址";
- 本地方法棧:略;
運行時數據區應該是你們關注的重點,由於大部分JVM性能調優工做集中在這運行時數據區(也有部分調優的工做是執行引擎作的,因此只能說大部分),特別垃圾機制對堆、方法區的影響;另外,平時你們沒有依據的增長堆內存或者棧內存,基本是都是無效的,或者是錯誤的;爲何這麼說,須要另篇文章才說得清楚;性能
Execution Engine(執行引擎)
Execution Engine(執行引擎)就是行爲就是執行指令集合,具體實現JVM規範定義的指令;直接和本地操做交互;執行引擎可使用多種執行技術:解釋、即時編譯、自適應優化等;自適應優化是目前執行引擎使用普遍的技術。測試
自適應優化的虛擬機開始時候都是解釋運行的,可是它會監視執行狀況。它會自動識別那些是程序"熱區",而後把"熱區"代碼編譯成本地代碼,很是仔細地優化這些代碼,以達更好性能要求。因此平時壓力測試時,要先讓程序跑一會,才能達到執行引擎的正常的狀態。優化
Java線程模型
Java虛擬機規範定義的線程模型,目標是有助於在很體系結構上都實現它,在可能的狀況下使用本地線程。使用本地線程的好處就是,Java線程能夠不一樣的處理器上並行工做。關於線程的內容也很大,這裏只有備忘下,有時間另起一篇文章介紹。
- 虛擬規範沒有假設不一樣優先級的線程採用時間分片方式。因此在不一樣體系的JVM所實現的分片方式是不同的,多線程的程序不能依賴線程優先級。
- 虛擬機的規範中,Java的線程行爲術語是經過-變量、主存、和工做內存,來定義的。因此咱們上面介紹JVM沒有出現過主存、工做內存的術語,是由於這是虛擬機規範的用語,具體映射到JVM時有更詳細的術語和說法。但這並非說,虛擬機規範和實現不統一,虛擬機規範只是規定虛擬機要實現的功能,並不關心虛擬機怎麼實現。這是我剛開始學JVM很困惑的地方,由於網上不少都說JVM的內存模型,實際上是線程模型,線程模型包含了主存和工做內存的工做方式。
- Java虛擬機規範定義許多規則用來管理線程和主存之間的低層交互行爲。基本上,管理低層的行爲規則能夠解讀爲:
- 把變量的值從主存拷貝到它的工做內存。
- 把值從它的工做內存寫回主存。
與線程模型有密切關係的Java關鍵字volatile,感興趣的能夠本身瞭解下。或者回複評論,我進一步解釋。由於這個與虛擬機不太相關了。