JVM_03 运行时数据区[ 堆 ]
一、堆的概述
①. 一個JVM實(shí)例只存在一個堆內(nèi)存,堆也是Java內(nèi)存管理的核心區(qū)域
②. Java堆區(qū)在JVM啟動的時候即被創(chuàng)建,其空間大小也是確定的。是Jvm管理最大的一塊內(nèi)存空間
③. 堆可以在物理上不連續(xù)的內(nèi)存空間中,但在邏輯上是連續(xù)的
④. 所有的線程共享Java堆,在這里還可以劃分線程私有的緩沖區(qū)(Thread Local Allocation Buffer,TLAB)
⑤. 在方法結(jié)束后,堆中的對象不會馬上被移除,僅僅在垃圾收集的時候才有被移除 (注意:一個進(jìn)程就是一個JVM實(shí)例,一個進(jìn)程中包含多個線程)
二、堆的內(nèi)存結(jié)構(gòu)
- ①. 現(xiàn)在垃圾收集器大部分都基于分帶收集理論設(shè)計(jì)的,堆空間細(xì)分為:
- ②. jdk1.7 堆中的結(jié)構(gòu)
- ③. jdk 1.8 堆中的結(jié)構(gòu)
三、堆空間大小的設(shè)置
①. Java堆區(qū)用于存儲Java對象實(shí)例,那么堆的大小在JVM啟動時就已經(jīng)設(shè)定好了,大家可以通過選項(xiàng)"-Xmx 和 -Xms"來設(shè)置
②. -Xms(物理內(nèi)存的1/64):表示堆區(qū)的起始內(nèi)存,等價于-XX:InitialHeapSize
③. -Xmx(物理內(nèi)存的1/4):則用于表示堆區(qū)的最大內(nèi)存,等價于-XX:MaxHeapSize
④. 通常會將-Xms和-Xmx兩個參數(shù)配置相同的值,其目的是為了能夠在java垃圾回收機(jī)制清理完堆區(qū)后不需要重新分隔計(jì)算堆區(qū)的大小,從而提升性能
案列演示
package com.xiaozhi.heap;import java.util.concurrent.TimeUnit;/*** -Xms:600m* -Xmx:600m* 查看設(shè)置的參數(shù):* 方式一(cmd中):jps / jstat -gc 進(jìn)程id* 方式二(XX:+PrintGCDetails)*/ public class HeapDemo1 {public static void main(String[] args)throws Exception {//返回Java虛擬機(jī)中的堆內(nèi)存總量long initialMemory = Runtime.getRuntime().totalMemory()/1024/1024;//返回Java虛擬機(jī)試圖使用的最大堆內(nèi)存量long maxMemory = Runtime.getRuntime().maxMemory()/1024/1024;System.out.println("-Xms:"+initialMemory+"M");System.out.println("-Xmx:"+maxMemory+"M");//TimeUnit.SECONDS.sleep(1000000);} }四、新生代與老年代參數(shù)設(shè)置
配置新生代與老年代在堆結(jié)構(gòu)占比
默認(rèn):-XX:NewRatio=2,表示新生代占1,老年代占2,新生代占整個堆的1/3
可以修改-XX:NewRatio=4,表示新生代占1,老年代占4,新生代占整個堆的1/5
-XX:SurvivorRatio調(diào)整這個空間比例(Eden空間和另外兩個Survivor空間缺省所占的比例是8:1:1)
-Xmn:設(shè)置新生代最大內(nèi)存大小
幾乎所有的Java對象都是在Eden區(qū)被new出來的,覺大部分的Java對象的銷毀都在新生代進(jìn)行的
五、 復(fù)制算法重點(diǎn)
一般過程(圖解)
過大對象
復(fù)制算法詳解 掌握
(伊甸園滿了,就會觸發(fā)gc(minor gc),而gc就會把標(biāo)識為垃圾的對象干掉,不是垃圾的對象就要轉(zhuǎn)移到幸存區(qū),把伊甸園讓出來給新的對象用)
過程:
六、Minor GC | Major GC | Full GC
- 只針對新生代區(qū)域的GC,指發(fā)生在新生代的垃圾收集動作,因?yàn)榇蠖鄶?shù)Java對象存活率都不高,所以Minor GC非常頻繁,一般回收速度也比較快
- 當(dāng)Eden代滿,會觸發(fā)minor GC ,Survivor 滿不會引發(fā)GC minor gc
- 會引發(fā)STW,暫停其他用戶線程,等垃圾回收結(jié)束,用戶線程才能恢復(fù)
- major GC 是回收老年代的垃圾;
- major gc 的速度一般比Minor gc 慢10倍以上,STW時間更長
- full GC 就會出現(xiàn)所謂的STW(stop the world)現(xiàn)象,即所有的進(jìn)程都掛起等待清理垃圾
- full GC是回收老年代和年輕代的垃圾
- full GC是開發(fā)調(diào)優(yōu)中盡量避免的,這樣暫時時間會短一些
(指發(fā)生在老年代的垃圾收集動作,出現(xiàn)了Major GC,經(jīng)常會伴隨至少一次的Minor GC(但并不是絕對的)。Major GC的速度一般要比Minor GC慢上10倍以上)
七、針對不同年齡階段的對象分配原則如下所示
八、TLAB(Thread Local Allocation Buffer) 掌握
從內(nèi)存模型而不是垃圾收集的角度,對Eden區(qū)域繼續(xù)進(jìn)行劃分,JVM為每個線程分配了一個私有緩存區(qū)域,它包含在Eden空間內(nèi)
盡管不是所有的對象實(shí)例都能夠在TLAB中成功分配內(nèi)存,但JVM確實(shí)是將TLAB作為內(nèi)存分配的首選
默認(rèn)情況下,TLAB空間的內(nèi)存非常小,僅占有整個Eden空間的1%,當(dāng)然可通過選項(xiàng)"-XX:TLABWasteTargePercent"設(shè)置TLAB空間所占用Eden空間的百分比大小
一旦對象在TLAB空間分配內(nèi)存失敗時,JVM就會嘗試著通過使用加鎖機(jī)制確保數(shù)據(jù)操作的原子性,從而直接在Eden空間中分配內(nèi)存
圖解:
九、堆空間參數(shù)總結(jié)
-XX:+PrintFlagsInitial : 查看所有的參數(shù)的默認(rèn)初始值
-XX:+PrintFlagsFinal : 查看所有的參數(shù)的最終值(可能會存在修改(:表示修改了),不再是初始值)
具體查看某個參數(shù)的指令:
(jps:查看當(dāng)前運(yùn)行中的進(jìn)程
jinfo -flag SurvivorRatio 進(jìn)程id)
-Xms:初始堆空間內(nèi)存 (默認(rèn)為物理內(nèi)存的1/64)
-Xmx:最大堆空間內(nèi)存(默認(rèn)為物理內(nèi)存的1/4)
-Xmn:設(shè)置新生代的大小。(初始值及最大值)
-XX:NewRatio:配置新生代與老年代在堆結(jié)構(gòu)的占比
(默認(rèn):-XX:NewRatio=2,表示新生代占1,老年代占2,新生代占整個堆的1/3
可以修改-XX:NewRatio=4,表示新生代占1,老年代占4,新生代占整個堆的1/5)
-XX:SurvivorRatio:設(shè)置新生代中Eden和S0/S1空間的比例
(Eden空間和另外兩個Survivor空間缺省所占的比例是8:1:1)
-XX:MaxTenuringThreshold:設(shè)置新生代垃圾的最大年齡
-XX:+PrintGCDetails:輸出詳細(xì)的GC處理日志
(如下這兩種方式是簡單的打印
打印gc簡要信息:① -XX:+PrintGC ② -verbose:gc)
-XX:HandlePromotionFailure:是否設(shè)置空間分配擔(dān)保
(JDK6之后,只要老年代的連續(xù)空間大于新生代對象總大小或者歷次晉升的平均大小就會進(jìn)行Minor GC,否則將進(jìn)行Full GC)
總結(jié)
以上是生活随笔為你收集整理的JVM_03 运行时数据区[ 堆 ]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2021中国餐饮行业数字化调研报告
- 下一篇: JVM_03 运行时数据区 [ 方法区]