知識總結(jié)
一.JAVA虛擬機內(nèi)存劃分:
? ? ? ? 以常用的HotSpot虛擬機為研究對象附帽,JAVA虛擬機管理的內(nèi)存大致包括以下幾個部分:程序計數(shù)器埠戳、虛擬機棧、本地方法棧蕉扮、堆整胃、方法區(qū)、運行時常量池慢显。
? ? ? ? 程序計數(shù)器:可以把它看做是當前線程所執(zhí)行的字節(jié)碼的行號指示器爪模。不論是單核還是多核的CPU,每個線程都會有一個獨立的程序計數(shù)器荚藻,因而程序計數(shù)器是線程私有的屋灌。
? ? ? ? 虛擬機棧:它就是我們常說的“棧內(nèi)存”,用來存放與方法有關(guān)的局部變量信息应狱、方法出口等共郭。虛擬機執(zhí)行每個方法時,都會從“棧內(nèi)存”中劃分出一個“棧幀”供此方法單獨使用疾呻。因為特定的“棧幀”只被某個特定的線程獨享除嘹,所以虛擬機棧也是線程私有的。
? ? ? ? 本地方法棧:本地方法棧與虛擬機棧的功能相似岸蜗,唯一的區(qū)別是尉咕,本地方法棧只為虛擬機調(diào)用到的Native方法服務(wù)。
? ? ? ? 堆:堆內(nèi)存是虛擬機管理的最大一塊內(nèi)存璃岳,主要用于存放JAVA實例對象年缎。堆內(nèi)存是GC(垃圾收集器)管理的主要區(qū)域悔捶,目前GC主要采用分代收集算法。堆內(nèi)存被所有線程共享单芜。
? ? ? ? 方法區(qū):方法區(qū)用于存儲已被虛擬機加載的類信息蜕该、常量、靜態(tài)變量等洲鸠。方法區(qū)中的大部分數(shù)據(jù)都是“有進無出”的堂淡,通常只在“類卸載”和“常量池回收”兩種情況下,才會被GC回收掉一部分內(nèi)存扒腕。方法區(qū)被所有線程共享绢淀。
? ? ? ? 運行時常量池:運行時常量池是方法區(qū)的一部分,用于存放編譯期生成的各種字面量和符號引用袜匿。比如:我們通過非new的方式定義的String類型的值更啄,就存放在這里稚疹。
二.對象的創(chuàng)建過程
? ? ? ? 主要分為5步:一居灯,檢查對象涉及的所有類是否已完成加載内狗。二,為新生對象分配內(nèi)存空間柳沙。三赂鲤,將分配的內(nèi)存都初始化為零。四数初,對對象進行必要的信息設(shè)置。五车摄,執(zhí)行init方法仑鸥,完成對象的初始化。
三.對象的存儲結(jié)構(gòu):
? ? ? ? 對象在內(nèi)存中的存儲布局眼俊,分為3塊區(qū)域:對象頭疮胖、實例數(shù)據(jù)誊役、對齊填充谷市。
? ? ? ? 對象頭用于存儲對象自身的描述信息和元數(shù)據(jù)的類型指針,實例數(shù)據(jù)是存放對象內(nèi)容的主要區(qū)域鹏漆,對齊填充是為了適應(yīng)HotSpot虛擬機而做的地址偏移创泄,無實際意義鞠抑。
四.對象的訪問定位:
? ? ? ? 對象的訪問定位,主要有句柄和直接指針兩種方式搁拙。
? ? ? ? 句柄:在堆中劃分出一塊內(nèi)存作為句柄池,棧中保存句柄池的地址酪碘,句柄池中保存對象實例數(shù)據(jù)的指針和對象類型數(shù)據(jù)的指針兴垦,通過這兩個指針來尋找堆中的對象和該對象對應(yīng)的方法區(qū)中的類型數(shù)據(jù)字柠。
? ? ? ? 直接指針:棧中直接保存對象實例的內(nèi)存地址,對象類型數(shù)據(jù)的指針存儲在對象實例的內(nèi)存區(qū)域中钦幔。
? ? ? ? 采用句柄的方式数冬,可避免在對象移動過程中,頻繁修改棧中該對象的引用铜异。采用直接指針的方式秸架,可快速實現(xiàn)對象的內(nèi)存定位。目前蚂子,HotSpot虛擬機采用的是直接指針的方式。
個人感受
? ? ? ? 以前對虛擬機的認識食茎,都是碎片化的,很多地方都是“只知其然不知其所以然””鹩妫現(xiàn)在成體系地去了解,就能想清楚很多問題了~