JVM运行数据区-Java堆

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异常。

java 复制代码
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 space
    at heap.HeapSetDemo.main(HeapSetDemo.java:13)
    ```
相关推荐
Warren9818 分钟前
Java Record 类 — 简化不可变对象的写法
java·开发语言·jvm·分布式·算法·mybatis·dubbo
SimonKing22 分钟前
流式数据服务端怎么传给前端,前端怎么接收?
java·后端·程序员
Laplaces Demon24 分钟前
Spring 源码学习(十)—— DispatcherServlet
java·后端·学习·spring
哈基米喜欢哈哈哈32 分钟前
进程和线程
java·linux·windows·笔记
咕白m62534 分钟前
Java 高效实现 Word 转 PDF - 掌握关键转换选项
java
幼稚园的山代王35 分钟前
Kotlin数据类型
android·开发语言·kotlin
青春不流名1 小时前
-bash: ll: 未找到命令
开发语言·bash
都叫我大帅哥1 小时前
谁说数据库不能“直播”?用Debezium玩转实时数据流!
java
写bug写bug1 小时前
彻底搞懂Spring Boot的系统监控机制
java·后端·spring
啃火龙果的兔子2 小时前
Form.Item中判断其他Form.Item的值
开发语言·前端·javascript