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)```