Java堆
堆區(Heap區)是JVM運行時數據區占用內存最大的一塊區域,每一個JVM進程只存在一個堆區,它在JVM啟動時被創建,JVM規范中規定堆區可以是物理上不連續的內存,但必須是邏輯上連續的內存。
1、堆區是線程共享共享的區域,同時也是JVM管理最大的內存區域。
2、JVM規范中描述,所有的對象實例及數組都應該在運行時分配在堆上。而他們的引用會被保存在虛擬機棧中,當方法結束,這些實例不會被立即清除,而是等待垃圾回收。
3、由于堆占用內存大,所以是垃圾回收的重點區域。
堆區的組成
堆區的組成分為年輕代(Young Generation)、老年代(Old Generation),年輕代被分為伊甸區和幸存者區,幸存區又被分為Survivor 0(S0)和Survivor 1(S1)。年輕代和老年代比例為1:2,伊甸區和S0、S1比例為8:1:1,當然這個比例都是可以通過JVM參數設置,不同區域存放的對象不同:
1、伊甸區(Eden) :存放大部分新創建對象。
2、幸存區(Survivor):存放Minor GC 之后,Eden區和幸存區(Survivor)本身沒有被回收的對象。
3、老年代:存放Minor GC之后且年齡計數器達到15依然存活的對象、Major GC和Full GC之后仍然存活的對象。
堆空間的大小設置
1、-Xms、-Xmx和-Xmn
Java堆的內存大小是可修改的,默認情況下,初始堆內存為物理內存的1/64,最大為物理內存的1/4。
-Xms:設置初始堆內存,如-Xms64m
-Xmx: 設置最大堆內存,如-Xmx64m
—Xmn: 設置年輕代內存,如-Xmx32m
2、各內存區域比例
年輕代與老年代默認為1:2,可通過-XX:NewRatio參數修改,如-XX:NewRatio=4,即為1:4
伊甸區和S0、S1區默認為8:1:1,可通過-XX:SurvivorRatio參數修改,如-XX:SurvivorRatio=6,通過監測發現設置,以后并不是6:1:1,這是因為Java堆的內存分配策略,關閉內存分配策略,-XX:-UseAdaptiveSizePolicy
3、內存溢出
當JVM無法申請到足夠內存給堆空間或者沒有足夠的空間存儲當前堆中的對象,就會出現java.lang.OutOfMemoryError。
驗證內存溢出
設置-Xmx128m -XX:+PrintGCDetails(打印GC日志),執行如下程序,創建一個128M數組,該數組既無法在eden區存放,也無法在老年代存放,同時,也會觸發一次Full GC,Full GC之后,依然無法存放,拋出OMM異常。
public class HeapSetDemo {public static void main(String[] args) {byte[] b = new byte[1024 * 1024 * 128];}
}
[GC (Allocation Failure) [PSYoungGen: 2007K->856K(38400K)] 2007K->864K(125952K), 0.0007477 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 856K->808K(38400K)] 864K->816K(125952K), 0.0005979 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 808K->0K(38400K)] [ParOldGen: 8K->611K(87552K)] 816K->611K(125952K), [Metaspace: 3210K->3210K(1056768K)], 0.0040897 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 0K->0K(38400K)] 611K->611K(125952K), 0.0002508 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(38400K)] [ParOldGen: 611K->593K(87552K)] 611K->593K(125952K), [Metaspace: 3210K->3210K(1056768K)], 0.0042290 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceat heap.HeapSetDemo.main(HeapSetDemo.java:13)```