欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JVM入門之JVM內(nèi)存結(jié)構(gòu)內(nèi)容詳解

 更新時間:2021年09月01日 08:38:50   作者:那股泥石流  
這篇文章主要介紹了JVM入門之JVM內(nèi)存結(jié)構(gòu)內(nèi)容詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下

一、java代碼編譯執(zhí)行過程

  1. 源碼編譯:通過Java源碼編譯器將Java代碼編譯成JVM字節(jié)碼(.class文件)
  2. 類加載:通過ClassLoader及其子類來完成JVM的類加載
  3. 類執(zhí)行:字節(jié)碼被裝入內(nèi)存,進入JVM虛擬機,被解釋器解釋執(zhí)行

   注:Java平臺由Java虛擬機和Java應用程序接口搭建,Java語言則是進入這個平臺的通道,

      用Java語言編寫并編譯的程序可以運行在這個平臺上

二、JVM簡介

1.java程序經(jīng)過一次編譯之后,將java代碼編譯為字節(jié)碼也就是class文件,然后在不同的操作系統(tǒng)上依靠不同的java虛擬機進行解釋,最后再轉(zhuǎn)換為不同平臺的機器碼,最終得到執(zhí)行

2.Java虛擬機(JVM) 處在核心的位置,是程序與底層操作系統(tǒng)、硬件無關(guān)的關(guān)鍵。

    JVM的下方是移植接口,移植接口由兩部分組成:適配器和Java操作系統(tǒng), 其中依賴于平臺的部分稱為適配器,JVM 通過移植接口在具體的平臺和操作系統(tǒng)上實現(xiàn)

    JVM 的上方是Java的基本類庫和擴展類庫以及它們的API, 利用Java API編寫的應用程序(application) 和小程序(Java applet) 可以在任何Java平臺上運行而無需考慮底層平臺

    Java虛擬機(JVM)實現(xiàn)了程序與操作系統(tǒng)的分離,從而實現(xiàn)了Java 的跨平臺

3.JVM在它的生存周期中有一個明確的任務,那就是運行Java程序,因此當Java程序啟動的時候,就產(chǎn)生JVM的一個實例;當程序運行結(jié)束的時候,該實例也跟著消失了

4.三種JVM:① Sun公司的HotSpot  ② BEA公司的JRockit  ③ IBM公司的J9 JVM

    在JDK1.7及其以前我們所使用的都是Sun公司的HotSpot,但由于Sun公司和BEA公司都被oracle收購,jdk1.8將采用Sun公司的HotSpot和BEA公司的JRockit兩個JVM中精華形成jdk1.8的JVM。

三、JVM體系結(jié)構(gòu)

1.Class Loader類加載器
       負責加載 .class文件,class文件在文件開頭有特定的文件標示,并且ClassLoader負責class文件的加載等,至于它是否可以運行,則由Execution Engine決定。
 ?、?定位和導入二進制class文件
  ② 驗證導入類的正確性
 ?、?為類分配初始化內(nèi)存
  ④ 幫助解析符號引用.
2.Native Interface本地接口
  本地接口的作用是融合不同的編程語言為Java所用,它的初衷是融合C/C++程序,Java誕生的時候C/C++橫行的時候,要想立足,必須有調(diào)用C/C++程序,于是就在內(nèi)存中專門開辟了一塊區(qū)域處理標記為
  native的代碼,它的具體作法是Native Method Stack中登記native方法,在Execution Engine執(zhí)行時加載native libraies。
  目前該方法使用的越來越少了,除非是與硬件有關(guān)的應用,比如通過Java程序驅(qū)動打印機,或者Java系統(tǒng)管理生產(chǎn)設(shè)備,在企業(yè)級應用中已經(jīng)比較少見。
  因為現(xiàn)在的異構(gòu)領(lǐng)域間的通信很發(fā)達,比如可以使用Socket通信,也可以使用Web Service等。
3.Execution Engine 執(zhí)行引擎:執(zhí)行包在裝載類的方法中的指令,也就是方法。
4.Runtime data area 運行數(shù)據(jù)區(qū)(即:虛擬機內(nèi)存或者JVM內(nèi)存 下節(jié)介紹)
      從整個計算機內(nèi)存中開辟一塊內(nèi)存存儲Jvm需要用到的對象,變量等,分為:方法區(qū),堆,虛擬機棧,程序計數(shù)器,本地方法棧。

四、JVM內(nèi)存結(jié)構(gòu)

1.程序計數(shù)器 PC Register

  每個線程都有一個程序計算器,就是一個指針,指向方法區(qū)中的方法字節(jié)碼(下一個將要執(zhí)行的指令代碼),由執(zhí)行引擎讀取下一條指令,是一個非常小的內(nèi)存空間,幾乎可以忽略不記。

  程序計數(shù)器(Program Counter Register)是一塊較小的內(nèi)存空間,它的作用可以看做是當前線程所執(zhí)行的字節(jié)碼的行號指示器。在虛擬機的概念模型里(僅是概念模型,各種虛擬機可能會通過一些更高效的方式去實現(xiàn)),字節(jié)碼解釋器工作時就是通過改變這個計數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令,分支、循環(huán)、跳轉(zhuǎn)、異常處理、線程恢復等基礎(chǔ)功能都需要依賴這個計數(shù)器來完成。由于Java 虛擬機的多線程是通過線程輪流切換并分配處理器執(zhí)行時間的方式來實現(xiàn)的,在任何一個確定的時刻,一個處理器(對于多核處理器來說是一個內(nèi)核)只會執(zhí)行一條線程中的指令。因此,為了線程切換后能恢復到正確的執(zhí)行位置,每條線程都需要有一個獨立的程序計數(shù)器,各條線程之間的計數(shù)器互不影響,獨立存儲,我們稱這類內(nèi)存區(qū)域為“線程私有”的內(nèi)存。如果線程正在執(zhí)行的是一個Java 方法,這個計數(shù)器記錄的是正在執(zhí)行的虛擬機字節(jié)碼指令的地址;如果正在執(zhí)行的是Natvie 方法,這個計數(shù)器值則為空(Undefined)。此內(nèi)存區(qū)域是唯一一個在Java 虛擬機規(guī)范中沒有規(guī)定任何OutOfMemoryError 情況的區(qū)域。

2.本地方法棧 Native Method Stack

  Native Method Stack中登記native方法,在Execution Engine執(zhí)行時加載native libraies

  本地方法棧與虛擬機棧基本類似,區(qū)別在于虛擬機棧為虛擬機執(zhí)行的java方法服務,而本地方法棧則是為Native方法服務

3.方法區(qū)  Method Area

  用于存儲虛擬機加載的:靜態(tài)變量+常量+類信息+運行時常量池 (類信息:類的版本、字段、方法、接口、構(gòu)造函數(shù)等描述信息 )

  默認最小值為16MB,最大值為64MB,可以通過-XX:PermSize 和 -XX:MaxPermSize 參數(shù)限制方法區(qū)的大小

  對于習慣在HotSpot 虛擬機上開發(fā)和部署程序的開發(fā)者來說,很多人愿意把方法區(qū)稱為“永久代”(Permanent Generation),本質(zhì)上兩者并不等價,僅僅是因為HotSpot 虛擬機的設(shè)計團隊選擇把GC 分代收集擴展至方法區(qū),或者說使用永久代來實現(xiàn)方法區(qū)而已。對于其他虛擬機(如BEA JRockit、IBM J9 等)來說是不存在永久代的概念的。即使是HotSpot 虛擬機本身,根據(jù)官方發(fā)布的路線圖信息,現(xiàn)在也有放棄永久代并“搬家”至Native Memory 來實現(xiàn)方法區(qū)的規(guī)劃了。Java 虛擬機規(guī)范對這個區(qū)域的限制非常寬松,除了和Java 堆一樣不需要連續(xù)的內(nèi)存和可以選擇固定大小或者可擴展外,還可以選擇不實現(xiàn)垃圾收集。相對而言,垃圾收集行為在這個區(qū)域是比較少出現(xiàn)的,但并非數(shù)據(jù)進入了方法區(qū)就如永久代的名字一樣“永久”存在了。這個區(qū)域的內(nèi)存回收目標主要是針對常量池的回收和對類型的卸載,一般來說這個區(qū)域的回收“成績”比較難以令人滿意,尤其是類型的卸載,條件相當苛刻,但是這部分區(qū)域的回收確實是有必要的。在Sun 公司的BUG 列表中,曾出現(xiàn)過的若干個嚴重的BUG 就是由于低版本的HotSpot 虛擬機對此區(qū)域未完全回收而導致內(nèi)存泄漏。根據(jù)Java 虛擬機規(guī)范的規(guī)定,當方法區(qū)無法滿足內(nèi)存分配需求時,將拋出OutOfMemoryError 異常。

4.棧 JVM Stack

  編譯器可知的各種基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)、對象引用(引用指針,并非對象本身)

  棧是java 方法執(zhí)行的內(nèi)存模型:

  每個方法被執(zhí)行的時候 都會創(chuàng)建一個“棧幀”用于存儲局部變量表(包括參數(shù))、操作棧、方法出口等信息。

  每個方法被調(diào)用到執(zhí)行完的過程,就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程。

 ?。ň植孔兞勘恚捍娣帕司幾g器可知的各種基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)、對象引用(引用指針,并非對象本身),

  其中64位長度的long和double類型的數(shù)據(jù)會占用2個局部變量的空間,其余數(shù)據(jù)類型只占1個。

  局部變量表所需的內(nèi)存空間在編譯期間完成分配,當進入一個方法時,這個方法需要在棧幀中分配多大的局部變量是完全確定的,在運行期間棧幀不會改變局部變量表的大小空間)

  棧的生命期是跟隨線程的生命期,線程創(chuàng)建時創(chuàng)建,線程結(jié)束棧內(nèi)存也就釋放,是線程私有的。

5.堆  Java Heap

  所有的對象實例以及數(shù)組都要在堆上分配,此內(nèi)存區(qū)域的唯一目的就是存放對象實例

  堆是Java 虛擬機所管理的內(nèi)存中最大的一塊。Java 堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機啟動時創(chuàng)建

  堆是理解Java GC機制最重要的區(qū)域,沒有之一

  結(jié)構(gòu):新生代(Eden區(qū)+2個Survivor區(qū))  老年代   永久代(HotSpot有)

  新生代:新創(chuàng)建的對象——>Eden區(qū) 

  GC之后,存活的對象由Eden區(qū) Survivor區(qū)0進入Survivor區(qū)1   

  再次GC,存活的對象由Eden區(qū) Survivor區(qū)1進入Survivor區(qū)0 

  老年代:對象如果在新生代存活了足夠長的時間而沒有被清理掉(即在幾次Young GC后存活了下來),則會被復制到老年代

  如果新創(chuàng)建對象比較大(比如長字符串或大數(shù)組),新生代空間不足,則大對象會直接分配到老年代上(大對象可能觸發(fā)提前GC,應少用,更應避免使用短命的大對象)

  老年代的空間一般比新生代大,能存放更多的對象,在老年代上發(fā)生的GC次數(shù)也比年輕代少

  永久代:可以簡單理解為方法區(qū)(本質(zhì)上兩者并不等價)

  如上文所說:對于習慣在HotSpot 虛擬機上開發(fā)和部署程序的開發(fā)者來說,很多人愿意把方法區(qū)稱為“永久代”,本質(zhì)上兩者并不等價

  僅僅是因為HotSpot 虛擬機的設(shè)計團隊選擇把GC 分代收集擴展至方法區(qū),或者說使用永久代來實現(xiàn)方法區(qū)而已

  對于其他虛擬機(如BEA JRockit、IBM J9 等)來說是不存在永久代的概念的

  即使是HotSpot 虛擬機本身,根據(jù)官方發(fā)布的路線圖信息,現(xiàn)在也有放棄永久代并“搬家”至Native Memory 來實現(xiàn)方法區(qū)的規(guī)劃了

  Jdk1.6及之前:常量池分配在永久代

  Jdk1.7:有,但已經(jīng)逐步“去永久代”

  Jdk1.8及之后:沒有永久代(java.lang.OutOfMemoryError: PermGen space,這種錯誤將不會出現(xiàn)在JDK1.8中)

6.直接內(nèi)存  Direct Memor

  直接內(nèi)存并不是JVM管理的內(nèi)存,可以這樣理解,直接內(nèi)存,就是JVM以外的機器內(nèi)存,比如,你有4G的內(nèi)存,JVM占用了1G,則其余的3G就是直接內(nèi)存

  JDK中有一種基于通道(Channel)和緩沖區(qū)(Buffer)的內(nèi)存分配方式,將由C語言實現(xiàn)的native函數(shù)庫分配在直接內(nèi)存中,用存儲在JVM堆中的DirectByteBuffer來引用

  由于直接內(nèi)存收到本機器內(nèi)存的限制,所以也可能出現(xiàn)OutOfMemoryError的異常。

參考資料

1.JVM工作原理 

2.JVM運行原理詳解

3.Java 內(nèi)存區(qū)域和GC機制

4.深入理解JVM基本原理

到此這篇關(guān)于JVM入門之JVM內(nèi)存結(jié)構(gòu)內(nèi)容詳解的文章就介紹到這了,更多相關(guān)JVM入門之JVM內(nèi)存結(jié)構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論