知識(shí)總結(jié)
一.JAVA虛擬機(jī)內(nèi)存劃分:
? ? ? ? 以常用的HotSpot虛擬機(jī)為研究對(duì)象,JAVA虛擬機(jī)管理的內(nèi)存大致包括以下幾個(gè)部分:程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧、堆、方法區(qū)、運(yùn)行時(shí)常量池。
? ? ? ? 程序計(jì)數(shù)器:可以把它看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。不論是單核還是多核的CPU,每個(gè)線程都會(huì)有一個(gè)獨(dú)立的程序計(jì)數(shù)器,因而程序計(jì)數(shù)器是線程私有的。
? ? ? ? 虛擬機(jī)棧:它就是我們常說的“棧內(nèi)存”,用來存放與方法有關(guān)的局部變量信息、方法出口等。虛擬機(jī)執(zhí)行每個(gè)方法時(shí),都會(huì)從“棧內(nèi)存”中劃分出一個(gè)“棧幀”供此方法單獨(dú)使用。因?yàn)樘囟ǖ摹皸敝槐荒硞€(gè)特定的線程獨(dú)享,所以虛擬機(jī)棧也是線程私有的。
? ? ? ? 本地方法棧:本地方法棧與虛擬機(jī)棧的功能相似,唯一的區(qū)別是,本地方法棧只為虛擬機(jī)調(diào)用到的Native方法服務(wù)。
? ? ? ? 堆:堆內(nèi)存是虛擬機(jī)管理的最大一塊內(nèi)存,主要用于存放JAVA實(shí)例對(duì)象。堆內(nèi)存是GC(垃圾收集器)管理的主要區(qū)域,目前GC主要采用分代收集算法。堆內(nèi)存被所有線程共享。
? ? ? ? 方法區(qū):方法區(qū)用于存儲(chǔ)已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量等。方法區(qū)中的大部分?jǐn)?shù)據(jù)都是“有進(jìn)無出”的,通常只在“類卸載”和“常量池回收”兩種情況下,才會(huì)被GC回收掉一部分內(nèi)存。方法區(qū)被所有線程共享。
? ? ? ? 運(yùn)行時(shí)常量池:運(yùn)行時(shí)常量池是方法區(qū)的一部分,用于存放編譯期生成的各種字面量和符號(hào)引用。比如:我們通過非new的方式定義的String類型的值,就存放在這里。
二.對(duì)象的創(chuàng)建過程
? ? ? ? 主要分為5步:一,檢查對(duì)象涉及的所有類是否已完成加載。二,為新生對(duì)象分配內(nèi)存空間。三,將分配的內(nèi)存都初始化為零。四,對(duì)對(duì)象進(jìn)行必要的信息設(shè)置。五,執(zhí)行init方法,完成對(duì)象的初始化。
三.對(duì)象的存儲(chǔ)結(jié)構(gòu):
? ? ? ? 對(duì)象在內(nèi)存中的存儲(chǔ)布局,分為3塊區(qū)域:對(duì)象頭、實(shí)例數(shù)據(jù)、對(duì)齊填充。
? ? ? ? 對(duì)象頭用于存儲(chǔ)對(duì)象自身的描述信息和元數(shù)據(jù)的類型指針,實(shí)例數(shù)據(jù)是存放對(duì)象內(nèi)容的主要區(qū)域,對(duì)齊填充是為了適應(yīng)HotSpot虛擬機(jī)而做的地址偏移,無實(shí)際意義。
四.對(duì)象的訪問定位:
? ? ? ? 對(duì)象的訪問定位,主要有句柄和直接指針兩種方式。
? ? ? ? 句柄:在堆中劃分出一塊內(nèi)存作為句柄池,棧中保存句柄池的地址,句柄池中保存對(duì)象實(shí)例數(shù)據(jù)的指針和對(duì)象類型數(shù)據(jù)的指針,通過這兩個(gè)指針來尋找堆中的對(duì)象和該對(duì)象對(duì)應(yīng)的方法區(qū)中的類型數(shù)據(jù)。
? ? ? ? 直接指針:棧中直接保存對(duì)象實(shí)例的內(nèi)存地址,對(duì)象類型數(shù)據(jù)的指針存儲(chǔ)在對(duì)象實(shí)例的內(nèi)存區(qū)域中。
? ? ? ? 采用句柄的方式,可避免在對(duì)象移動(dòng)過程中,頻繁修改棧中該對(duì)象的引用。采用直接指針的方式,可快速實(shí)現(xiàn)對(duì)象的內(nèi)存定位。目前,HotSpot虛擬機(jī)采用的是直接指針的方式。
個(gè)人感受
? ? ? ? 以前對(duì)虛擬機(jī)的認(rèn)識(shí),都是碎片化的,很多地方都是“只知其然不知其所以然”?,F(xiàn)在成體系地去了解,就能想清楚很多問題了~