亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

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

   注:Java平臺(tái)由Java虛擬機(jī)和Java應(yīng)用程序接口搭建,Java語言則是進(jìn)入這個(gè)平臺(tái)的通道,

      用Java語言編寫并編譯的程序可以運(yùn)行在這個(gè)平臺(tái)上

二、JVM簡介

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2.本地方法棧 Native Method Stack

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

  本地方法棧與虛擬機(jī)?;绢愃?,區(qū)別在于虛擬機(jī)棧為虛擬機(jī)執(zhí)行的java方法服務(wù),而本地方法棧則是為Native方法服務(wù)

3.方法區(qū)  Method Area

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

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

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

4.棧 JVM Stack

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

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

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

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

  (局部變量表:存放了編譯器可知的各種基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)、對(duì)象引用(引用指針,并非對(duì)象本身),

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

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

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

5.堆  Java Heap

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

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

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

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

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

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

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

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

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

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

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

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

  僅僅是因?yàn)镠otSpot 虛擬機(jī)的設(shè)計(jì)團(tuán)隊(duì)選擇把GC 分代收集擴(kuò)展至方法區(qū),或者說使用永久代來實(shí)現(xiàn)方法區(qū)而已

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

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

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

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

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

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

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

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

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

參考資料

1.JVM工作原理 

2.JVM運(yùn)行原理詳解

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

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)文章

最新評(píng)論