一鳍徽、模型圖
二、JVM內(nèi)存分區(qū)
JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)的內(nèi)存有:方法區(qū)舆驶、Java堆橱健、Java棧、本地方法棧沙廉、程序計(jì)數(shù)器
方法區(qū):方法區(qū)是被所有線程共享的內(nèi)存區(qū)域拘荡,用來(lái)存儲(chǔ)已被虛擬機(jī)加載的類信息、常量撬陵、靜態(tài)變量珊皿、JTI(just in time,即時(shí)編譯技術(shù))編譯后的代碼等數(shù)據(jù)。運(yùn)行時(shí)常量池是方法區(qū)的一部分巨税,用于存放編譯期間生成的各種字面常量和符號(hào)引用蟋定。平時(shí)通過(guò)反射獲取到的類型、方法名草添、字段名稱驶兜、訪問(wèn)修飾符等信息就是從方法區(qū)獲取到的。在使用到CGLib對(duì)類進(jìn)行增強(qiáng)時(shí)远寸,增強(qiáng)的類越多抄淑,就需要越大的方法區(qū)類存儲(chǔ)動(dòng)態(tài)生成的Class信息,當(dāng)存放方法區(qū)數(shù)據(jù)的內(nèi)存溢出時(shí)驰后,會(huì)報(bào)OutOfMemoryError異常肆资,在jdk1.8中也就是Metaspace內(nèi)存溢出,可以通過(guò)參數(shù)JVM參數(shù)-XX:MetaspaceSize和-XX:MaxMetaspaceSize設(shè)置Metaspace的空間大小灶芝。
-
Java堆(Heap):和方法區(qū)一樣是被所有線程共享的內(nèi)存區(qū)域郑原,是JVM中最大的一塊內(nèi)存區(qū)域,幾乎所有的對(duì)象實(shí)例都是在這個(gè)區(qū)域進(jìn)行內(nèi)存的分配的夜涕,為對(duì)象分配內(nèi)存主要有兩種方式:
- 指針碰撞法:把堆中的內(nèi)存進(jìn)行劃分(已分配的內(nèi)存+空閑的內(nèi)存)犯犁,通過(guò)指針作為分界點(diǎn),當(dāng)需要分內(nèi)存時(shí)女器,把指向空閑內(nèi)存移動(dòng)與對(duì)象大小相等的距離栖秕。
- 空閑列表法:JVM通過(guò)維護(hù)一個(gè)列表,記錄可用的內(nèi)存塊信息晓避,當(dāng)分配操作發(fā)生時(shí)簇捍,從列表中找到一個(gè)足夠大的內(nèi)存分配給對(duì)象實(shí)例,并更新列表上的記錄俏拱。
-
Java棧(Java Stack):又稱之為虛擬機(jī)棧暑塑,存放的是棧幀(棧的基礎(chǔ)單位), 是用來(lái)存儲(chǔ)數(shù)據(jù)和部分過(guò)程結(jié)果的數(shù)據(jù)結(jié)構(gòu)。
Java棧.png
其中:
1.局部變量表:用于存儲(chǔ)方法參數(shù)和方法內(nèi)部定義的局部變量锅必,對(duì)于非static方法事格,局部變量表存儲(chǔ)的第0個(gè)位置存儲(chǔ)的為當(dāng)前對(duì)象的引用惕艳,可以通過(guò)關(guān)鍵字this進(jìn)行訪問(wèn),方法參數(shù)按照參數(shù)列表順序驹愚,從第1個(gè)位置分配下去远搪;
2.操作數(shù)棧:用于操作運(yùn)行過(guò)程中的各種中間結(jié)果與字節(jié)碼指令;
3.動(dòng)態(tài)鏈接:程序運(yùn)行過(guò)程中逢捺,將符號(hào)引用解析為直接引用谁鳍,例如多態(tài),對(duì)象的引用在程序運(yùn)行時(shí)鏈接到具體的實(shí)現(xiàn)類;
4.出口記錄:程序的出口 本地方法棧(Native Method Stack)
本地方法棧是與Java棧發(fā)揮的作用十分相似,區(qū)別是Java棧執(zhí)行的是Java方法(也就是字節(jié)碼)服務(wù)劫瞳,而本地方法棧則為虛擬機(jī)使用到的本地方法服務(wù)倘潜,可能底層調(diào)用的c或者c++,我們打開(kāi)jdk安裝目錄可以看到也有很多用c編寫的文件,可能就是本地方法所調(diào)用的c代碼志于。程序計(jì)數(shù)器(Program Counter Register):用來(lái)記錄當(dāng)前方法執(zhí)行的情況涮因,為了在線程切換可以恢復(fù)到正確執(zhí)行位置,每個(gè)線程都需有獨(dú)立的一個(gè)程序計(jì)數(shù)器伺绽,不同線程之間的程序計(jì)數(shù)器互不影響养泡,獨(dú)立存儲(chǔ)。
注意:如果線程執(zhí)行的是個(gè)java方法奈应,那么計(jì)數(shù)器記錄虛擬機(jī)字節(jié)碼指令的地址澜掩。如果為native【底層方法】,那么計(jì)數(shù)器為空钥组。這塊內(nèi)存區(qū)域是虛擬機(jī)規(guī)范中唯一沒(méi)有OutOfMemoryError的區(qū)域输硝。
注:Java棧今瀑、本地方法棧程梦、程序計(jì)數(shù)器生命周期一樣,都是線程私有橘荠,隨線程的創(chuàng)建而創(chuàng)建