?初見(jiàn)JVM內(nèi)存區(qū)域
????? JVM一個(gè)重要的機(jī)制就是自動(dòng)內(nèi)存管理機(jī)制,為了深入理解JVM的內(nèi)存管理機(jī)制,了解JVM的內(nèi)存的分區(qū)以及各個(gè)分區(qū)的作用是基礎(chǔ),本文主要總結(jié)java虛擬機(jī)的內(nèi)存區(qū)域分類以及各個(gè)內(nèi)存區(qū)域的作用。
? java內(nèi)存的分區(qū)及其作用
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖1 JVM內(nèi)存的分區(qū)
????? ?從圖1中可以知道,在劃分具體內(nèi)存區(qū)域之前,可以依據(jù)內(nèi)存是否是線程公有而進(jìn)行一次大的劃分:
????? (1)線程公有:所有的線程都公用的一塊內(nèi)存區(qū)域,隨jvm的啟動(dòng)而創(chuàng)建,隨jvm的銷毀而銷毀。線程公有的內(nèi)存區(qū)域其生命周期和JVM的生命周期保持一致。
????? (2)線程私有:線程私有的內(nèi)存區(qū)域,其隨線程的創(chuàng)建而創(chuàng)建,隨線程的銷毀而銷毀,是每個(gè)線程都獨(dú)立擁有的一塊內(nèi)存區(qū)域,其生命周期和線程保持一致,和jvm不保持一致。
????? 在了解了線程公有和線程私有的概念之后,逐一介紹各個(gè)內(nèi)存區(qū)域的左右。
????? 1.程序計(jì)數(shù)器,這是一個(gè)最特殊的內(nèi)存區(qū)域,存放了維護(hù)線程上下文切換所需要的信息。其主要維護(hù)了一個(gè)指向當(dāng)前執(zhí)行指令的指針PC,當(dāng)一個(gè)線程所擁有的時(shí)間片耗盡的時(shí)候會(huì)交出cpu的使用權(quán),在退出之前通過(guò)PC指針記錄當(dāng)前指令執(zhí)行的位置,這樣在下一次獲得CPU分配的時(shí)間片后,通過(guò)PC指針可以繼續(xù)上次未完成的任務(wù)。
????? 2.虛擬機(jī)棧,虛擬機(jī)棧是開(kāi)發(fā)中最常接觸的內(nèi)存區(qū)域,比如在方法中定義的變量和引用都是存放在虛擬機(jī)棧中。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖 2 虛擬機(jī)棧的內(nèi)存結(jié)構(gòu)
????? 對(duì)比圖2的虛擬機(jī)棧內(nèi)存結(jié)構(gòu),我們來(lái)介紹虛擬機(jī)棧的作用:
????? (1)每個(gè)方法,都對(duì)應(yīng)一個(gè)幀棧,在方法中定義的變量和引用,以及其他的方法執(zhí)行和調(diào)用信息都存放在幀棧中
????? (2)每調(diào)用一個(gè)方法,該方法對(duì)應(yīng)的幀棧就被壓入虛擬機(jī)棧中,當(dāng)方法執(zhí)行完畢后,對(duì)應(yīng)的幀棧就從虛擬機(jī)棧中出棧。
????? (3)從上述的過(guò)程中,不難分析方法調(diào)用對(duì)應(yīng)一次壓棧和出棧的過(guò)程,這是有時(shí)間開(kāi)銷的過(guò)程,所以說(shuō)遞歸執(zhí)行的代碼時(shí)間效率往往是底下的。
????? (4)每個(gè)方法對(duì)應(yīng)的幀棧都需要消耗一定的內(nèi)存空間,而虛擬機(jī)棧的內(nèi)存空間是有限的,當(dāng)方法的調(diào)用層次過(guò)深的時(shí)候就會(huì)有stackOverFlow異常發(fā)生。
3.本地方法棧
本地方法棧的作用其實(shí)和虛擬機(jī)棧的職能完全一致,虛擬機(jī)棧是為java方法服務(wù)的內(nèi)存區(qū)域,而本地方法棧是為native方法服務(wù)的區(qū)域,除此之外本地方法棧的和虛擬機(jī)棧并無(wú)區(qū)分。
4.堆區(qū)(Heap)
堆區(qū)也是開(kāi)發(fā)人員最常接觸的內(nèi)存區(qū)域,java中的對(duì)象以及數(shù)組都是存放在堆區(qū)中的,堆區(qū)的內(nèi)存可以是物理上連續(xù)的內(nèi)存空間,也可以是邏輯上聯(lián)系的內(nèi)存空間。是JVM所管理的最大的內(nèi)存區(qū)域,容易發(fā)生內(nèi)存泄漏和內(nèi)存溢出,是垃圾回收算法重點(diǎn)照顧的區(qū)域。下面看一下java中的對(duì)象是如何在堆區(qū)中存儲(chǔ)的。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖3 java中對(duì)象的內(nèi)存布局
從圖3中可以看出 java中的對(duì)象在內(nèi)存中的存儲(chǔ)由三部分組合:
(1)對(duì)象頭,對(duì)象頭的第一部分存儲(chǔ)對(duì)象自身運(yùn)行時(shí)所需要的數(shù)據(jù)入圖中所示,第二部分中的類型指針用來(lái)指示這個(gè)對(duì)象是哪個(gè)類的事例,假如對(duì)象是數(shù)組類型的話,還需要存儲(chǔ)數(shù)組的長(zhǎng)度信息。
(2)實(shí)例數(shù)據(jù),實(shí)例數(shù)據(jù)是對(duì)象真正存儲(chǔ)的有效區(qū)域,對(duì)象中定義的各種類型的變量,無(wú)論是從父類繼承的還是子類定義的都是存放在這個(gè)部分。
(3)對(duì)齊填充,這部分并無(wú)實(shí)際的含義,假如對(duì)象的內(nèi)存大小不是8字節(jié)的整數(shù)倍,就填充數(shù)據(jù),使對(duì)象的內(nèi)存數(shù)據(jù)大小是8字節(jié)的整數(shù)倍。
5.方法區(qū)
方法區(qū)同樣也是開(kāi)發(fā)人員常見(jiàn)用的內(nèi)存區(qū)域,比如靜態(tài)變量,常量以及虛擬加載的類信息都是存放在方法區(qū)中的。
java對(duì)象的創(chuàng)建和訪問(wèn)的過(guò)程
????? 上節(jié)中,介紹了JVM的內(nèi)存的分區(qū)以及各個(gè)區(qū)域的作用,有了上述的基本知識(shí)之后,我們通過(guò)對(duì)象的創(chuàng)建和訪問(wèn)的過(guò)程,來(lái)直觀的感受jvm各個(gè)內(nèi)存的分工。
????? 一丶對(duì)象創(chuàng)建過(guò)程
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖 1 java中對(duì)象創(chuàng)建的一般過(guò)程
二丶對(duì)象定位過(guò)程
1.基于句柄的對(duì)象定位
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖 2 java中基于句柄的對(duì)象訪問(wèn)方式
2.基于直接地址的對(duì)象定位
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 圖3 java中基于直接地址的對(duì)象定位
Reference:[1]周志明 深入理解java虛擬機(jī)-JVM高級(jí)特性與最佳實(shí)踐[M],機(jī)械工業(yè)出版社.
原文CSDN博客鏈接?https://blog.csdn.net/qq_30322803/article/details/78632753