摘要:主要在堆上分配內(nèi)存,而堆又分為新生代和老年代兩個(gè)部分,新生代又再分為區(qū)和區(qū)兩部分,本文根據(jù)堆的劃分,描述的內(nèi)存分配策略。
java主要在堆上分配內(nèi)存,而Java堆又分為新生代(YoungGen)和老年代(OldGen)兩個(gè)部分,新生代又再分為Eden區(qū)和Survivor區(qū)兩部分,本文根據(jù)java堆的劃分,描述hotspot的內(nèi)存分配策略。
GC垃圾收集分類Minor GC: 發(fā)生在新生代中的垃圾收集,采用復(fù)制算法。
Major GC/Full GC: 發(fā)生在老年代的垃圾收集動(dòng)作,所采用的是標(biāo)記-清除或者標(biāo)記-整理算法。
Eden區(qū)和Survivor區(qū)對(duì)于采用復(fù)制算法的虛擬機(jī),新生代通常有一個(gè)Eden區(qū)和兩個(gè)Survivor區(qū)。
對(duì)象優(yōu)先在Eden區(qū)分配,當(dāng)Eden區(qū)沒有足夠的空間進(jìn)行分配時(shí),虛擬機(jī)講發(fā)起一次Minor GC,Eden中存活的對(duì)象將被移動(dòng)到第一塊Survivor區(qū)S1,Eden被清空。
當(dāng)Eden區(qū)再次填滿,再次觸發(fā)Minor GC,Eden區(qū)和S1中的存活對(duì)象被復(fù)制送入第二塊Survivor區(qū)S2中,S1和Eden被清空,下一輪交換S1和S2的角色。
使用兩個(gè)Survivor區(qū)能夠簡(jiǎn)化復(fù)制算法的過(guò)程,并且避免復(fù)制過(guò)程中內(nèi)存碎片的產(chǎn)生。
當(dāng)對(duì)象的復(fù)制次數(shù)達(dá)到-XX:MaxTenuringThreshold設(shè)置的值(默認(rèn)-XX:MaxTenuringThreshold=15)時(shí),將被移至老年代。
實(shí)驗(yàn)/** * VM Options: * -Xmx20M 堆最大20M * -Xms20M 堆最小20M * -Xmn10M 新生代為10M * -XX:SurvivorRatio=8 Eden區(qū)和Survivor區(qū)的比值為8:1 * -XX:+PrintGCDetails 輸出回收日志及退出時(shí)內(nèi)存各區(qū)域情況 */ private static final int _1MB = 1024 * 1024; public static void testAllocation(){ byte[] allocation1,allocation2,allocation3,allocation4; allocation1 = new byte[2 * _1MB]; allocation2 = new byte[2 * _1MB]; allocation3 = new byte[2 * _1MB]; allocation4 = new byte[4 * _1MB]; }
結(jié)果:
PSYoungGen total 9216K, used 7479K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000) eden space 8192K, 91% used [0x00000007bf600000,0x00000007bfd4df10,0x00000007bfe00000) from space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000) to space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000) ParOldGen total 10240K, used 4096K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000) object space 10240K, 40% used [0x00000007bec00000,0x00000007bf000010,0x00000007bf600000) Metaspace used 2692K, capacity 4486K, committed 4864K, reserved 1056768K class space used 288K, capacity 386K, committed 512K, reserved 1048576K
在退出時(shí)各個(gè)區(qū)域結(jié)果如上, PSYoungGen的PS指的是Parallel Scavenge垃圾回收器,ParOldGen中的Par指的是Parallel Old垃圾回收器。
設(shè)置中堆為10M,新生代為10M,因此老年代為10M。設(shè)置SurvivorRatio為8:1,因此Eden區(qū)大小為8M,Survivor區(qū)大小為1M。因?yàn)镾urvivor區(qū)同一時(shí)刻只有一個(gè)能用于分配,因此PSYoungGen區(qū)域總可用大小為9M。
在allocation4進(jìn)行分配時(shí),新生代eden區(qū)已經(jīng)用了6M,只剩2M,無(wú)法進(jìn)行分配,觸發(fā)MinorGC。新生代中3個(gè)2M大小的對(duì)象全部無(wú)法放入1M的Survivor區(qū)中,所以只能通過(guò)分配擔(dān)保機(jī)制將兩個(gè)2M的對(duì)象放入老年代中,再將allocation4的4M對(duì)象放入Eden區(qū)中。
最終Eden區(qū)分配6M,survivor區(qū)中沒有對(duì)象,老年代分配4M。
大對(duì)象是指需要大量連續(xù)內(nèi)存空間的Java對(duì)象。為了避免在Eden區(qū)及兩個(gè)Survivor區(qū)之間發(fā)生大量的內(nèi)存復(fù)制,虛擬機(jī)提供了-XX:PretenureSizeThreshold參數(shù)。大于該參數(shù)設(shè)置值的對(duì)象將直接分配在老年代。
長(zhǎng)期存活對(duì)象直接進(jìn)入老年代虛擬機(jī)給每個(gè)對(duì)象定義了一個(gè)對(duì)象年齡計(jì)數(shù)器,對(duì)象每經(jīng)過(guò)一個(gè)MinorGC仍然存活,則年齡加一,當(dāng)年齡增加到超過(guò)-XX:MaxTenuringThreshold設(shè)置的值(默認(rèn)為16)時(shí),將被移至老年代。
空間分配擔(dān)保如文章開頭的例子中,當(dāng)出現(xiàn)大量對(duì)象在MinorGC后仍然存活的情況,Survivor區(qū)無(wú)法容納多余的對(duì)象,此時(shí),需要老年代進(jìn)行分配擔(dān)保,把Survivor無(wú)法容納的對(duì)象直接進(jìn)入老年代。JDk 6 Update 24之后,擔(dān)保的規(guī)則是,只要老年代的連續(xù)空間大于新生代對(duì)象總大小或者歷次晉升的平均大小就會(huì)進(jìn)行MinorGC,否則將進(jìn)行Full GC。
參數(shù)設(shè)置小結(jié)參數(shù) | 描述 |
---|---|
-Xms20M | 堆最小值 |
-Xmx20M | 堆最大值 |
-Xmn10M | 新生代大小 |
-XX:SurvivorRatio=8 | Eden區(qū)比Survivor區(qū)的大小 |
-XX:+PrintGCDetails | 輸出回收日志和退出時(shí)各內(nèi)存區(qū)域情況 |
-XX:PretenureSizeThreshold=10M | 大于該參數(shù)設(shè)置值的對(duì)象直接分配在老年代 |
-XX:MaxTenuringThreshold=15 | 新生代對(duì)象年齡增加到超過(guò)該值時(shí),將被移至老年代 |
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69445.html
摘要:概要要理解的內(nèi)存管理策略,首先就要熟悉的運(yùn)行時(shí)數(shù)據(jù)區(qū),如上圖所示,在執(zhí)行程序的時(shí)候,虛擬機(jī)會(huì)把它所管理的內(nèi)存劃分為多個(gè)不同的數(shù)據(jù)區(qū),稱為運(yùn)行時(shí)數(shù)據(jù)區(qū)。 這是一篇有關(guān)JVM內(nèi)存管理的文章。這里將會(huì)簡(jiǎn)單的分析一下Java如何使用從物理內(nèi)存上申請(qǐng)下來(lái)的內(nèi)存,以及如何來(lái)劃分它們,后面還會(huì)介紹JVM的核心技術(shù):如何分配和回收內(nèi)存。 JMM ( Java Memory Model )概要 show...
摘要:目錄往期博客課堂篇初識(shí)常量池簡(jiǎn)單理解字符串常量池靜態(tài)常量池大整型常量池為什么要了解垃圾收集和內(nèi)存分配如何判斷對(duì)象已死引用計(jì)數(shù)算法可達(dá)性分析算法之后引用的擴(kuò)充回收方法區(qū)垃圾收集算法分代收集理論標(biāo)記清除標(biāo)記復(fù)制標(biāo)記整理對(duì)象分 ...
摘要:騰訊特約作者姚潮生首先以一個(gè)內(nèi)存泄露實(shí)例來(lái)開始本節(jié)基礎(chǔ)概念的內(nèi)容。堆內(nèi)存用于存放所有由創(chuàng)建的對(duì)象內(nèi)容包括該對(duì)象其中的所有成員變量和數(shù)組。回到我們的問(wèn)題,為什么內(nèi)存會(huì)泄露堆內(nèi)存中的長(zhǎng)生命周期的對(duì)象持有短生命周期對(duì)象的強(qiáng)軟引用,盡管 騰訊Bugly特約作者: 姚潮生 首先以一個(gè)內(nèi)存泄露實(shí)例來(lái)開始本節(jié)基礎(chǔ)概念的內(nèi)容。 實(shí)例1:?jiǎn)卫龑?dǎo)致內(nèi)存對(duì)象無(wú)法釋放而泄露 showImg(http://i....
摘要:虛擬機(jī)所處的區(qū)域,則表示它是屬于新生代收集器還是老年代收集器。虛擬機(jī)總共運(yùn)行了分鐘,其中垃圾收集花掉分鐘,那么吞吐量就是。收集器線程所占用的數(shù)量為。 本文主要從GC(垃圾回收)的角度試著對(duì)jvm中的內(nèi)存分配策略與相應(yīng)的垃圾收集器做一個(gè)介紹。 注:還是老規(guī)矩,本著能畫圖就不BB原則,盡量將各知識(shí)點(diǎn)通過(guò)思維導(dǎo)圖或者其他模型圖的方式進(jìn)行說(shuō)明。文字僅記錄額外的思考與心得,以及其他特殊情況 內(nèi)存...
摘要:內(nèi)存泄漏總結(jié)內(nèi)存管理的目的就是讓我們?cè)陂_發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問(wèn)題。在中,內(nèi)存泄漏的范圍更大一些。 Android 內(nèi)存泄漏總結(jié) 內(nèi)存管理的目的就是讓我們?cè)陂_發(fā)中怎么有效的避免我們的應(yīng)用出現(xiàn)內(nèi)存泄漏的問(wèn)題。內(nèi)存泄漏大家都不陌生了,簡(jiǎn)單粗俗的講,就是該被釋放的對(duì)象沒有釋放,一直被某個(gè)或某些實(shí)例所持有卻不再被使用導(dǎo)致 GC 不能回收。最近自己閱讀了大量相關(guān)的文檔資料,打...
閱讀 1075·2021-11-12 10:34
閱讀 1002·2021-09-30 09:56
閱讀 679·2019-08-30 15:54
閱讀 2616·2019-08-30 11:14
閱讀 1478·2019-08-29 16:44
閱讀 3220·2019-08-29 16:35
閱讀 2505·2019-08-29 16:22
閱讀 2455·2019-08-29 15:39