1杆查、JVM一共分為五個(gè)區(qū)扮惦,分別為方法區(qū)、堆亲桦、Java棧崖蜜、本地方法棧浊仆、程序計(jì)數(shù)器;
? 2豫领、方法區(qū)抡柿、堆為線程共享區(qū)域,GC會(huì)對(duì)二個(gè)區(qū)進(jìn)行垃圾回收等恐;
? 3洲劣、Java棧、本地方法棧课蔬、程序計(jì)數(shù)器為線程私有區(qū)域囱稽;
? 4、程序計(jì)數(shù)器:程序計(jì)數(shù)器是一塊較小的內(nèi)存空間二跋,是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器?程序計(jì)算器處于線程獨(dú)占區(qū)?如果線程執(zhí)行的是java方法战惊,記錄的是正在執(zhí)行的虛擬機(jī)字節(jié) 碼指令的地址,如果是native方法扎即,這個(gè)計(jì)數(shù)器值為undefined样傍;
? 5、Java棧:棧也叫棧內(nèi)存铺遂,主管Java程序的運(yùn)行衫哥,是在線程創(chuàng)建時(shí) 創(chuàng)建,它的生命期是跟隨線程的生命期襟锐,線程結(jié)束棧內(nèi)存也就釋放撤逢,對(duì)于棧來說不存在垃圾回收問題,只要線程一結(jié)束該棧就Over粮坞,生命周期和線程一致蚊荣,是線程私有的。8種基本類型的變量+對(duì)象的引用變量+實(shí)例方法都是在函數(shù)的棧內(nèi)存中分配莫杈,棧里有棧幀互例,有返回對(duì)象、本地變量表筝闹、操作數(shù)棧媳叨、動(dòng)態(tài)連接。
? 6关顷、本地方法棧:它的具體做法是NativeMethod Stack中登記native方法,在ExecutionEngine執(zhí)行時(shí)加載本地方法庫(kù)议双;
? 7痘番、方法區(qū):方法區(qū)是被所有線程共享,所有字段和方法字節(jié)碼汞舱,以及一些特殊方法如構(gòu)造函數(shù)伍纫,接口代碼也在此定義。簡(jiǎn)單說昂芜,所有定 義的方法的信息都保存在該區(qū)域翻斟,此區(qū)屬于共享區(qū)間。
? ? ? ? 類信息:類的版本 字段 方法 接口
? ? ? ? 靜態(tài)變量
? ? ? ? 常量
? ? ? ? 類信息(構(gòu)造方法/接口定義)
? ? ? ? 運(yùn)行時(shí)常量池
? 8说铃、堆:一個(gè)JVM實(shí)例只存在一個(gè)堆內(nèi)存访惜,堆內(nèi)存的大小是可以調(diào)節(jié)的。類加載器讀取了類文件后腻扇,需要把類债热、方法、常變量放到堆內(nèi)存中幼苛,保存所有引用類型的真實(shí)信息窒篱,以方便執(zhí)行器執(zhí)行。堆內(nèi)存邏輯上分為三部分:新生代+老年代+方法區(qū)
新生代分別分為:伊甸園舶沿、S0墙杯,S1
JVM自帶類裝載器
????? Bootstrap Class Loader:加載jre/lib/rt.jar?? 啟動(dòng)類加載器(Bootstrap)C++;
????? Extension Class Loader:加載jre/lib/ext/*.jar擴(kuò)展類加載器(Extension)Java括荡;
????? System Class Loader:加載classPath下面的類 系統(tǒng)類加載器高镐,加載當(dāng)前應(yīng)用的classpath的所有類;
對(duì)象的訪問定位
? ??建立對(duì)象是為了使用對(duì)象畸冲, java程序需要通過棧上的reference數(shù)據(jù)來操作堆上的具體對(duì)象嫉髓。由于reference類型在java虛擬機(jī)規(guī)范中之規(guī)定了一個(gè)指向?qū)ο蟮囊茫]有定義這個(gè)引用應(yīng)該通過何種方式定位邑闲、訪問堆中的對(duì)象的具體位置算行,所以對(duì)象訪問方式也取決于虛擬機(jī)的實(shí)現(xiàn)。目前主流的訪問方式有使用句柄和直接指針兩種苫耸。
句柄訪問
堆中將會(huì)劃分出一塊內(nèi)存來作為句柄池州邢,reference中存儲(chǔ)的就是對(duì)象的句柄地址,而句柄中包含了對(duì)象實(shí)例數(shù)據(jù)與類型數(shù)據(jù)格子的具體地址信息褪子。
指針訪問
使用直接指針訪問量淌,java堆中對(duì)象的布局就必須考慮如何放置訪問數(shù)據(jù)的相關(guān)信息,而reference中存儲(chǔ)的直接就是對(duì)象地址褐筛。
兩種對(duì)象訪問方式各有優(yōu)勢(shì)类少,使用句柄來訪問的最大好處就是reference中存儲(chǔ)的是穩(wěn)定的句柄地址,在對(duì)象被移動(dòng)(垃圾收集時(shí)移動(dòng)對(duì)象是非常普遍的)時(shí)只會(huì)改變句柄中的實(shí)例數(shù)據(jù)指針渔扎,而reference本身不需要修改。使用直接指針訪問方式的最大好處就是速度更快信轿,它節(jié)省了一次指針定位的時(shí)間開銷晃痴,由于對(duì)象的訪問在java中非常頻繁残吩,因此這類開銷積少成多之后也是一項(xiàng)非常可觀的執(zhí)行成本倘核。
垃圾回收
? 如何判斷對(duì)象為垃圾對(duì)象:引用計(jì)數(shù)法 可達(dá)性分析
? 回收算法:標(biāo)記清除泣侮、復(fù)制、標(biāo)記整理紧唱、分代算法
? 標(biāo)記清除:算法分為“標(biāo)記”和“清除”兩個(gè)階段:首先標(biāo)記出所有需要回收的對(duì)象活尊,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象。
主要不足有兩個(gè):
一個(gè)是效率問題漏益,標(biāo)記和清除兩個(gè)過程的效率都不高蛹锰;
一個(gè)是空間問題,標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片绰疤,空間碎片太多可能會(huì)導(dǎo)致以后在程序運(yùn)行過程中需要分配較大對(duì)象時(shí)铜犬,無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作。
? 復(fù)制:它將可用內(nèi)存按容量劃分為大小相等的兩塊轻庆,每次只使用其中的一塊癣猾。當(dāng)這一塊的內(nèi)存用完了,就將還存活著的對(duì)象復(fù)制到另外一塊上面余爆,然后再把已使用過的內(nèi)存空間一次清理掉纷宇。這樣使得每次都是對(duì)整個(gè)半?yún)^(qū)進(jìn)行內(nèi)存回收,內(nèi)存分配時(shí)也就不用考慮內(nèi)存碎片等復(fù)雜情況蛾方,只要移動(dòng)堆頂指針呐粘,按順序分配內(nèi)存即可,實(shí)現(xiàn)簡(jiǎn)單转捕,運(yùn)行高效作岖。只是這種算法的代價(jià)是將內(nèi)存縮小為了原來的一半,未免太高了一點(diǎn)五芝。
??標(biāo)記整理:標(biāo)記過程仍然與“標(biāo)記-清除”算法一樣痘儡,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活的對(duì)象都向一端移動(dòng)枢步,然后直接清理掉端邊界以外的內(nèi)存沉删。
? 分代算法