JVM運行時區(qū)域

JVM運行時區(qū)域

Java運行時區(qū)域

JVM運行時數(shù)據(jù)區(qū),主要包含兩大部分:線程共有的方法區(qū)(Method Area)堆(Heap),線程私有的虛擬機(jī)棧(VM Stack)本地方法棧(Native Method Stack)程序計數(shù)器(Program Counter Register)。在數(shù)據(jù)區(qū)下面的執(zhí)行引擎中又包含了:即時編譯器(JITCompiler)和垃圾收集器(GC)。GC主要用于回收線程共享的區(qū)域(方法區(qū)和堆),對于線程私有的內(nèi)存區(qū)域則方法執(zhí)行完畢后系統(tǒng)自動釋放。(在實際的程序中,線程私有的內(nèi)存區(qū)域會有很多份)。
對于整個運行時數(shù)據(jù)區(qū)而言,外部交互的模塊有執(zhí)行引擎、本地庫接口和類加載器

  • 程序計數(shù)器(線程私有)

是一塊較小的內(nèi)存空間,它的作用可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器。在虛擬機(jī)概念模型里,字節(jié)碼解釋器工作時就是通過改變這個計數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令。如果線程正在執(zhí)行的是一個Java方法,這個計數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址,如果正在執(zhí)行的是Native方法,這個計數(shù)器值則為空(Undefined)。此內(nèi)存區(qū)域是唯一一個在Java虛擬機(jī)規(guī)范中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域

  • JVM棧(線程私有)

生命周期同線程相同。描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法執(zhí)行時都會創(chuàng)建一個棧幀(Stack Frame)用于存儲局部變量表、操作棧、動態(tài)鏈接、方法出口等信息。每個方法被調(diào)用直至執(zhí)行完成的過程,就對應(yīng)著一個棧幀在虛擬機(jī)棧中從入棧到出棧的過程。
局部變量表存放了編譯期可知的各種基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)、引用類型和returnAddress類型(指向了一條字節(jié)碼指令的地址)。局部變量表所需的內(nèi)存空間在編譯期間完成分配,當(dāng)進(jìn)入一個方法時,這個方法需要在幀中分配多大的局部變量空間是完全確定的,在方法運行期間不會改變局部變量表的大小。
JVM規(guī)范對這個區(qū)域規(guī)定了兩種異常狀況:如果線程請求的棧深度大于虛擬機(jī)所允許的深度,將拋出StackOverflowError異常;如果虛擬機(jī)??梢詣討B(tài)擴(kuò)展(當(dāng)前大部分Java虛擬機(jī)可以動態(tài)擴(kuò)展),當(dāng)擴(kuò)展時無法申請到足夠的內(nèi)存時會拋出OutOfMemoryError異常。

  • 本地方法棧(線程私有)

本地方法棧與虛擬機(jī)棧所發(fā)揮的作用是非常相似的,其區(qū)別不過是虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則是為虛擬機(jī)使用到的Native方法服務(wù)。(HotSpot虛擬機(jī)直接把本地方法棧和虛擬機(jī)棧合二為一)。

  • Java堆(線程共享)

Java堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機(jī)啟動時創(chuàng)建。此內(nèi)存區(qū)域唯一目的就是存放對象實例,幾乎所有的對象實例都在這里分配內(nèi)存。Java虛擬機(jī)規(guī)范描述是,所有的對象實例以及數(shù)組都要在堆上分配。但是隨著JIT編譯器的發(fā)展與逃逸分析技術(shù)的逐漸成熟,棧上分配、標(biāo)量替換優(yōu)化技術(shù)將會導(dǎo)致一些微妙的變化發(fā)生,所有的對象都分配在堆上也漸漸變得不是那么“絕對”了。
Java堆是垃圾收集器管理的主要區(qū)域,因此很多時候也被稱為“GC堆”。
Java堆可以處于物理上不連續(xù)的內(nèi)存空間,只要邏輯上是連續(xù)的即可。主流的虛擬機(jī)都是按照可擴(kuò)展來實現(xiàn)的(通過-Xmx和-Xms控制)。如果在堆中沒有內(nèi)存來完成實例分配,并且堆也無法再擴(kuò)展時,將會拋出OutOfMemoryError異常。

  • 方法區(qū)(線程共享)

用于存儲已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)。
Java虛擬機(jī)規(guī)范對這個區(qū)域的限制非常寬松,除了和Java堆一樣不需要連續(xù)的內(nèi)存和可以選擇固定大小或者可擴(kuò)展外,還可以選擇不是先垃圾收集。相對而言,垃圾收集行為在這個區(qū)域是比較少出現(xiàn)的。這個區(qū)域的垃圾回收目標(biāo)主要是針對常量池的回收和對類型的卸載。
根據(jù)Java虛擬機(jī)規(guī)范的規(guī)定,當(dāng)方法區(qū)無法滿足內(nèi)存分配需求時,將拋出OutOfMemoryError異常。

  • 運行時常量池

運行時常量池是方法區(qū)的一部分。Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池(Constant Pool Table),用于存放編譯期間生成的各種字面量和符號引用。這部分內(nèi)容將在類加載后存放到方法區(qū)的運行時常量池中。
Java虛擬機(jī)對Class文件的每一部分(包括常量池)的格式都有嚴(yán)格的規(guī)定,每一個字節(jié)用于存儲哪種數(shù)據(jù)都必須符合規(guī)范上的要求,這樣才會被虛擬機(jī)認(rèn)可、裝載和執(zhí)行。但對于運行時常量池,Java虛擬機(jī)規(guī)范沒有做任何細(xì)節(jié)的要求,不同的提供商實現(xiàn)的虛擬機(jī)可以按照自己的需求來實現(xiàn)這個內(nèi)存區(qū)域。
運行時常量池相對于Class文件常量池的另外一個重要特征是具備動態(tài)性。運行期間也可以將新的常量放入池中,比如String類的intern()方法。
當(dāng)常量池?zé)o法再申請到內(nèi)存時,會拋出OutOfMemoryError異常。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 該系列文章主要是記錄下自己暑假這段時間的學(xué)習(xí)筆記,暑期也在實習(xí),抽空學(xué)了很多,每個方面的知識我都會另起一篇博客去記...
    Yanci516閱讀 1,029評論 0 2
  • JVM內(nèi)存模型Java虛擬機(jī)(Java Virtual Machine=JVM)的內(nèi)存空間分為五個部分,分別是: ...
    光劍書架上的書閱讀 2,772評論 2 26
  • .bashrc文件 這個文件主要保存?zhèn)€人的一些個性化設(shè)置,如命令別名、路徑等。一般位于~/.bashrc 上例通過...
    hui_mamba閱讀 300評論 0 0
  • 子曰:“非其鬼而祭之,諂也。見義不為,無勇也。” 先生說:“不是你當(dāng)祭的鬼而祭他,這是你存心諂媚。遇見你該當(dāng)做的事...
    一棵樹2016閱讀 213評論 0 1
  • 因為家里的一些事情休息了兩個月?;貋砗?,想起幾個月前公司組織集體辦理了一張中國銀行的信用卡。(在我的《工廠的生意最...
    劉北山閱讀 331評論 0 1

友情鏈接更多精彩內(nèi)容