探討Java虛擬機之虛擬機體系結構

   自工做以上,程序由於代碼越寫越多,變得愈來愈臃腫,效率也會變得愈來愈低,因而我總喜歡不斷去優化程序結構外,內存優化和性能調優。java

    要對Java程序進行內存優化和性能調優,須要瞭解虛擬機的內部原理,瞭解Java虛擬機的好處除了上述說起兩點好處。從更深一點的技術層面上看,瞭解Java虛擬機的規範和實現,將更加有助於咱們編寫高效、穩定的Java代碼。好比,假如瞭解Java虛擬機的內存模型,瞭解虛擬機的內存回收機制,那麼咱們就不會過度依賴它,而會在須要的時候顯式的"釋放內存"(Java代碼不能顯式釋放內存,可是能夠經過釋放對象引用告知垃圾回收器回收該對象須要被回收),以下降沒必要要的內存消耗;假如咱們瞭解Java棧的工做原理,那麼咱們就能夠經過減小遞歸層數,減小循環次數來下降堆棧溢出的風險。可能對於應用開發人員來講,可能不會直接去涉及這些Java虛擬機底層實現的工做,可是瞭解這些背景知識,或多或少,都會對咱們寫的程序產生潛移默化的好的影響。數組

 

本篇文章,將簡明扼要的說明Java虛擬機的體系結構和內存模型,若有用詞不妥或解釋不許確之處,請不吝指正,深感榮幸!網絡

Java 虛擬機體系結構多線程

wKioL1VyotSAjt7TAAD7miYMhjA634.jpg

類裝載子系統ide

Java虛擬機有兩種類裝載器,分別是啓動類裝載器和用戶自定義裝載器。
通類裝載子系統經過類的全限定名(包名和類名,網絡裝載還包括 URL)將 Class 裝載進運行時數據區。對於每個被裝載的類型,Java虛擬機都會建立一個java.lang.Class類的實例來表明該類型,該實例被放在內存中的堆區,而裝載的類型信息則位於方法區,這一點和全部其餘對象都是同樣的。
類裝載子系統在裝載一個類型前,除了要定位和導入對應的二進制class文件外,還要驗證導入類的正確性,爲類變量分配並初始化內存,以及解析符號引用爲直接引用,這些動做嚴格按照如下順序進行:
裝載——查找並裝載類型的二進制數據;
鏈接——執行驗證,準備以及解析(可選)性能

      驗證 確保被導入類型的正確性
      準備 爲類變量分配內存,並將其初始化爲默認值
      解析 把類型中的符號引用轉換爲直接應用
 優化


方法區spa


對於每個被類裝載子系統裝載的類型,虛擬機都會保存下列數據到方法區:
類型的全限定名
類型超類的全限定名(java.lang.Object沒有超類)
類型是類類型仍是接口類型
類型的訪問修飾符
任何直接超接口的全限定名有序列表
操作系統

 

除了上述基本類型信息,還將保存以下信息:
類型的常量池
字段信息(包括字段名、字段類型、字段修飾符)
方法信息(包括方法名、返回類型、參數的數量和類型、方法修飾符,若是方法不是抽象和本地的,還將保存方法的字節碼、操做數棧和該方法棧幀中的局部變量區的大小和異常表)
常量之外的全部類變量(其實就是類的靜態變量,由於靜態變量是全部實例共享的,且與類型直接相關,因此他們是類一級的變量,做爲類的成員被保存在方法區)
一個到類ClassLoader的引用
線程

Java代碼  收藏代碼

  1. //返回的就是剛纔保存的ClassLoader引用   

  2. String.class.getClassLoader();   

 一個到Class類的引用


 

Java代碼  收藏代碼

  1. //將返回剛纔保存的Class類的引用   

  2. String.class;  

   

注意,方法區也是能夠被垃圾回收器回收的,當一個類型再也不被引用且方法區內存不足時,虛擬機將卸載該類型,回收內存。

 


Java程序在運行時建立的全部類實例或數組都放在同一個堆中,而每個Java虛擬機也只有一個堆空間,全部線程將共享這一個堆(這就是一個多線程的Java程序會產生對象訪問的同步問題的緣由了)。
因爲每一種Java虛擬機都有對虛擬機規範的不一樣實現,因此咱們可能不知道每一種Java虛擬機在堆中是以何種形式表示對象實例的,不過咱們能夠經過下面這可能的實現來一窺端倪:


wKioL1VyovezeDdpAAFNZwXAWOo243.jpg

 

程序計數器


對於運行中的Java程序而言,每個線程都有本身的PC(程序計數器)寄存器,它是在該線程啓動時建立的,大小爲一個字長,用來保存須要被執行的下一行代碼的位置。

 

 

Java棧


每個線程都有一個Java棧,以棧幀爲單位保存線程的運行狀態。虛擬機對Java棧的操做有兩種:壓棧和出棧,兩者都已幀爲單位。棧幀保存了傳入參數、局部變量、中間運算結果等數據,在方法完成時被彈出,而後釋放。
看一下兩個局部變量相加時棧幀的內存快照

wKiom1VyoZ_QrIQrAADSRQFh6Mg605.jpg

本地方法棧


這是 Java 調用操做系統本地庫的地方,用來實現 JNI(Java Native Interface,Java 本地接口)

 

執行引擎

Java虛擬機的核心,控制裝入 Java 字節碼並解析;對於運行中的Java程序而言,每個線程都是一個獨立的虛擬機執行引擎的實例,從線程生命週期的開始到結束,他要麼在執行字節碼,要麼在執行本地方法。


本地接口

鏈接了本地方法棧和操做系統庫。

 

注:文中全部提到"Java虛擬機"的地方都是指"JavaEE和JavaSE平臺的Java虛擬機規範"。

相關文章
相關標籤/搜索