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