JVM學(xué)習(xí)筆記(二)——運(yùn)行時(shí)數(shù)據(jù)區(qū)域

image-20200420162443578.png

一、 程序計(jì)數(shù)器

記錄正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址(如果正在執(zhí)行的是本地方法則為空)

二、 Java 虛擬機(jī)棧

每個(gè)Java方法在執(zhí)行的同時(shí)會(huì)創(chuàng)建一個(gè)棧幀用于存儲(chǔ)局部變量表、操作數(shù)棧、常量池引用等信息。從方法調(diào)用直至執(zhí)行完成的過(guò)程,對(duì)應(yīng)著一個(gè)棧幀在Java虛擬機(jī)中入棧和出棧的過(guò)程。

image-20200420165558681.png

可以通過(guò)-Xss這個(gè)虛擬機(jī)參數(shù)來(lái)指定每個(gè)線程的Java虛擬機(jī)內(nèi)存大小,在JDK1.4中默認(rèn)為256K,而在JDK1.5+默認(rèn)為1M:

java -Xss2m HackTheJava

該區(qū)域可能拋出如下異常:

  • 當(dāng)線程請(qǐng)求的棧的深度超過(guò)最大值,會(huì)拋出StackOverflowError異常;
  • 棧進(jìn)行動(dòng)態(tài)擴(kuò)展時(shí)如果無(wú)法申請(qǐng)到足夠內(nèi)存,會(huì)拋出OutOfMemoryError異常。

三、本地方法棧

本地方法棧與Java虛擬機(jī)棧類似,它們之間的區(qū)別只不過(guò)是本地方法棧為本地方法服務(wù)。

本地方法一般是用其它語(yǔ)言(C, C++或匯編語(yǔ)言等)編寫(xiě)的,并且被編譯為基于本機(jī)硬件和操作系統(tǒng)的程序,對(duì)待這些方法需要特別處理。

image-20200420172317944.png

四、堆

所有對(duì)象都在這里分配內(nèi)存,是垃圾收集的主要區(qū)域(“GC 堆”)。

現(xiàn)代的垃圾收集器基本都是采用分代收集算法,其主要思想是針對(duì)不同類型的對(duì)象采取不同的垃圾回收算法。可以將堆分成兩塊:

  • 新生代(Young Generation)
  • 老年代(Old Generation)

堆不需要連續(xù)內(nèi)存,并且可以動(dòng)態(tài)增加其內(nèi)存,增加失敗會(huì)拋出OutOfMemoryError異常。

可以通過(guò)-Xms-Xmx這兩個(gè)虛擬機(jī)參數(shù)來(lái)指定一個(gè)程序的堆內(nèi)存大小,第一個(gè)參數(shù)設(shè)置初始值,第二個(gè)參數(shù)設(shè)置最大值。

java -Xms1M -Xmx2M HackTheJava

五、方法區(qū)

用于存放已被加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。

和堆一樣不需要連續(xù)的內(nèi)存,并且可以動(dòng)態(tài)擴(kuò)展,動(dòng)態(tài)擴(kuò)展失敗一樣會(huì)拋出OutOfMemoryError異常。

對(duì)這塊區(qū)域進(jìn)行垃圾回收的主要目標(biāo)是對(duì)常量池的回收和對(duì)類的卸載,但是一般比較難實(shí)現(xiàn)。

Hotspot虛擬機(jī)把它當(dāng)成永久代來(lái)進(jìn)行垃圾回收。但是很難確定永久代的大小,因?yàn)樗艿胶芏嘁蛩赜绊?,并且每次Full GC之后永久代的大小都會(huì)改變,所以經(jīng)常會(huì)拋出OutOfMemoryError異常。為了更容易管理方法區(qū),從JDK1.8開(kāi)始,移除永久代,并把方法區(qū)移至元空間,它位于本地內(nèi)存中,而不是虛擬機(jī)內(nèi)存中。

方法區(qū)是一個(gè)JVM規(guī)范,永久代和元空間都是其一種實(shí)現(xiàn)方式。在JDK1.8之后,原來(lái)永久代的數(shù)據(jù)被分到堆和元空間中。元空間存儲(chǔ)類的元信息,靜態(tài)變量和常量池放入堆中。

六、運(yùn)行時(shí)常量池

運(yùn)行時(shí)常量池是方法區(qū)的一部分。

Class 文件中的常量池(編譯器生成的字面量和符號(hào)引用)會(huì)在類加載后被放入這個(gè)區(qū)域。

七、直接內(nèi)存

在 JDK 1.4 中新引入了 NIO 類,它可以使用 Native 函數(shù)庫(kù)直接分配堆外內(nèi)存,然后通過(guò) Java 堆里的 DirectByteBuffer 對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作。這樣能在一些場(chǎng)景中顯著提高性能,因?yàn)楸苊饬嗽诙褍?nèi)存和堆外內(nèi)存來(lái)回拷貝數(shù)據(jù)。

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

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

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