java内存高水位_jvm(1)---java内存结构
jvm主要由三個(gè)子系統(tǒng)構(gòu)成:類(lèi)加載子系統(tǒng),運(yùn)行時(shí)數(shù)據(jù)區(qū),執(zhí)行引擎
運(yùn)行時(shí)數(shù)據(jù)區(qū)主要包括:
1.本地方法棧:登記native方法,執(zhí)行時(shí)加載本地方法庫(kù)
2.程序計(jì)數(shù)器:就是一個(gè)指針,用來(lái)存儲(chǔ)指向下一條執(zhí)行指令的地址,也就是即將要執(zhí)行的指令代碼,是一個(gè)非常小得空間,可以忽略不計(jì)。
3.java棧:java線(xiàn)程執(zhí)行方法的內(nèi)存模型,一個(gè)線(xiàn)程對(duì)應(yīng)一個(gè)棧,每個(gè)方法在執(zhí)行時(shí)都會(huì)創(chuàng)建一個(gè)棧幀,用于存儲(chǔ)局部變量表(引用),操作數(shù)棧,動(dòng)態(tài)鏈接,方法出口等信息,不存在垃圾回收問(wèn)題,生命周期和線(xiàn)程一致,線(xiàn)程結(jié)束該棧就釋放。可以通過(guò)-Xss來(lái)設(shè)置棧空間。
4.方法區(qū):類(lèi)的所有字段和方法字節(jié)碼,以及一些特殊的方法,構(gòu)造函數(shù),接口定義,所有定義的方法的信息都存放在這。此外還包括靜態(tài)變量,常量,運(yùn)行時(shí)常量池
5.java堆:虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建,用于存放對(duì)象實(shí)例,幾乎所有的對(duì)象都在堆上面分配內(nèi)存,當(dāng)對(duì)象無(wú)法在該空間申請(qǐng)到內(nèi)存就會(huì)拋出OutMemoryError異常,同時(shí)也是垃圾回收器主要管理的區(qū)域,可以通過(guò)-Xmx/Xms來(lái)設(shè)置最大/最小堆
其中1.2.3都是線(xiàn)程私有,4.5線(xiàn)程共享
線(xiàn)程私有java棧圖解:
java堆詳解:
新生代:類(lèi)誕生、成長(zhǎng)、消亡的區(qū)域,一個(gè)類(lèi)在這里產(chǎn)生,應(yīng)用,最后被垃圾回收器收集,結(jié)束生命。
新生代分為兩部分: 伊甸園區(qū)(Eden space:亞當(dāng),夏娃造人,這名字取得還是很有意義的)和幸存者區(qū)(Survivor pace) ,所有的類(lèi)都是在伊甸園被new出來(lái)的。幸存區(qū)有兩個(gè): 0區(qū)(Survivor 0 space(From))和1區(qū)(Survivor 1 space(To))。當(dāng)伊甸園的空間用完時(shí),程序又需要?jiǎng)?chuàng)建對(duì)象,JVM的垃圾回收器將對(duì)伊甸園區(qū)進(jìn)行垃圾回收(Minor GC),將伊甸園區(qū)中的不再被其他對(duì)象所引用的對(duì)象進(jìn)行銷(xiāo)毀。然后將伊甸園中的剩余對(duì)象移動(dòng)到幸存From。若幸From也滿(mǎn)了,再對(duì)該區(qū)進(jìn)行垃圾回收,然后移動(dòng)到To。From到To操作一次,還存在To中的對(duì)象就相當(dāng)于長(zhǎng)了一歲,默認(rèn)是15歲,如果到了15歲都還存在有引用,那么就放入老年代,可以用過(guò)-XX:MaxTenuringThreshold來(lái)設(shè)置這個(gè)年齡
老年代:新生代經(jīng)過(guò)多次GC仍然存活的對(duì)象移動(dòng)到老年區(qū)。若老年區(qū)也滿(mǎn)了,那么這個(gè)時(shí)候?qū)a(chǎn)生FullGC,進(jìn)行老年區(qū)的內(nèi)存清理。若老年區(qū)執(zhí)行了Full GC之后發(fā)現(xiàn)依然無(wú)法進(jìn)行對(duì)象的保存,就會(huì)產(chǎn)生OOM異?!癘utOfMemoryError”??梢酝^(guò)減少FullGC來(lái)提高jvm性能
永久代(元數(shù)據(jù)):jdk1.8元數(shù)據(jù)區(qū)取代了永久代,本質(zhì)和永久代類(lèi)似,都是對(duì)JVM規(guī)范中方法區(qū)的實(shí)現(xiàn),區(qū)別在于元數(shù)據(jù)區(qū)并不在虛擬機(jī)中,而是使用本地物理內(nèi)存,永久代在虛擬機(jī)中,永久代邏輯結(jié)構(gòu)上屬于堆,但是物理上不屬于堆,堆大小=新生代+老年代。元數(shù)據(jù)區(qū)也有可能發(fā)生OutOfMemory異常。
Jdk1.6及之前: 有永久代, 常量池在方法區(qū)
Jdk1.7:有永久代,但已經(jīng)逐步“去永久代”,常量池在堆
Jdk1.8及之后: 無(wú)永久代,常量池在元空間
元數(shù)據(jù)區(qū)的動(dòng)態(tài)擴(kuò)展,默認(rèn)–XX:MetaspaceSize值為21MB的高水位線(xiàn)。一旦觸及則Full GC將被觸發(fā)并卸載沒(méi)有用的類(lèi)(類(lèi)對(duì)應(yīng)的類(lèi)加載器不再存活),然后高水位線(xiàn)將會(huì)重置。新的高水位線(xiàn)的值取決于GC后釋放的元空間。如果釋放的空間少,這個(gè)高水位線(xiàn)則上升。如果釋放空間過(guò)多,則高水位線(xiàn)下降。
使用-XX:+PrintGCDetails參數(shù)打印GC日志,運(yùn)行下面代碼:
package jvm;
/**
* @author: create by nijunyang
* @date:2019/6/19
*/
public class Test {
public static void main(String[] args)
{
byte[] bytes1 = new byte[62000*1024];
byte[] bytes2 = new byte[10240*1024];
byte[] bytes3 = new byte[30000*1024];
// byte[] bytes4 = new byte[28000*1024];
// byte[] bytes5 = new byte[10240*1024];
}
}
可以看到伊甸園區(qū)只有65536K,byte1->62000K 大對(duì)象被直接移入了老年代,因?yàn)?Survivor區(qū)大小無(wú)法存放該對(duì)象,所以在yong gc的時(shí)候直接將該對(duì)象放入老年代,
我們也可以通過(guò)設(shè)置-XX:PretenureSizeThreshold= 60000,使得創(chuàng)建大于60000字節(jié)的對(duì)象直接放入老年代。但是該參數(shù)只在Serial 和ParNew兩個(gè)垃圾收集器下面生效
byte2,byte3依然在伊甸園
放開(kāi)bytes4之后會(huì)發(fā)現(xiàn)From區(qū)也有占用了99%,差不多就是bytes2的大小,說(shuō)明bytes2移入了From,byte3也移入了老年代(byte1+byte3 = 92000K)
總結(jié)
以上是生活随笔為你收集整理的java内存高水位_jvm(1)---java内存结构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: Microsoft 登陆微软账号一直加载
- 下一篇: CocoaChina12月源码精选
