一、內(nèi)存模型
程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧、java堆、方法區(qū)
1、程序計(jì)數(shù)器
屬于線程的私有內(nèi)存空間,伴隨線程創(chuàng)建。每個(gè)線程都有一個(gè)獨(dú)立的程序計(jì)數(shù)器,用于記錄下一條要運(yùn)行的指令,各線程間互相獨(dú)立。如果當(dāng)前線程正在執(zhí)行一個(gè)java方法,則程序計(jì)數(shù)器記錄正在執(zhí)行額java字節(jié)碼地址,如果當(dāng)前線程正在執(zhí)行一個(gè)native方法,則程序計(jì)數(shù)器置為空
2、java虛擬機(jī)棧
屬于線程的私有內(nèi)存空間,伴隨線程創(chuàng)建,保存了方法的局部變量、部分結(jié)果、并參與方法的調(diào)用和返回。java棧大小可以是動(dòng)態(tài)或固定的。會(huì)引起 StackOverFlowError和OutOfMemeryError。
2.1如果線程請(qǐng)求的棧深度超過(guò)最大可用的棧深度,會(huì)拋出StackOverFlowError;如果棧可以動(dòng)態(tài)擴(kuò)展,而在擴(kuò)展過(guò)程中,沒(méi)有足夠的內(nèi)存空間來(lái)支持棧的空間,則會(huì)拋出OutOfMemeryError。
比如死循環(huán)遞歸:
?int i =0;
static void concreate()
{
i++;
concreate();? //會(huì)由于棧調(diào)用深度導(dǎo)致棧溢出
}????
main (){
concreate();?
}
當(dāng)設(shè)置 -Xss后,可以增加部分調(diào)用深度。
虛擬機(jī)棧在運(yùn)行時(shí)采用 棧幀的數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)上下文數(shù)據(jù),當(dāng)調(diào)用深度很深時(shí),會(huì)導(dǎo)致內(nèi)存膨脹。如圖:

3、本地方法棧
本地方法棧類似于虛擬機(jī)棧,也屬于線程私有內(nèi)存空間,java虛擬機(jī)棧用于管理java函數(shù)調(diào)用,而本地方法棧用于管理本地方法的調(diào)用,本地方法不是java實(shí)現(xiàn),而是C實(shí)現(xiàn)。也會(huì)拋出堆棧異常和內(nèi)存異常。
4、java堆
屬于所有線程共享的部分,幾乎所有的對(duì)象和數(shù)組都是在堆中分配空間的,java堆分為新生代和老年代,新生代用于存放剛剛產(chǎn)生的和年輕的對(duì)象,如果對(duì)象一直未回收,就會(huì)被移到老年代。新生代又分為Eden、s0、s1,s0和s1屬于survivor區(qū),也就是其中存儲(chǔ)的對(duì)象至少經(jīng)過(guò)了一次垃圾回收??梢酝ㄟ^(guò)-Xmx和-Xms控制,屬于GC的重點(diǎn)范圍

5、方法區(qū)
與堆空間類似,屬于所有線程共享的部分,保存的信息是類的元數(shù)據(jù)。方法區(qū)中最為重要的是類的類型信息、常量池、域信息、方法信息。類型信息包括類的完整名稱、父類的完整名稱、類型修飾符、類的直接接口類表;常量池包括類方法、域等信息所引用的常量信息;域信息包括域名稱、域類型、域修飾符;方法信息包括方法名稱、返回類型、方法參數(shù)、方法修飾符、方法字節(jié)碼 ,保存的信息大部分來(lái)源于.class文件,在hot spot 虛擬機(jī)中,也稱謂永久區(qū),對(duì)永久區(qū)的回收通常為:1.對(duì)永久區(qū)常量池的回收 2.永久區(qū)對(duì)類元數(shù)據(jù)的回收
設(shè)置 PermSize 和MaxPermSize來(lái)優(yōu)化
整體預(yù)覽圖:
