JVM 堆空间

概述

  • 一个 JVM 实例中只存在一个堆内存,是 Java 内存管理的核心区域。在 JVM 启动时创建堆。
  • 《Java 虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但是在逻辑上它应该被视为连续的
  • 所有的线程共享 Java 堆,在这里还可以划分线程私有的缓冲区(Thread Local Allocation Buffer,TLAB)
  • 几乎所有的对象实例以及数组都应当在运行时分配在堆上,所以在栈帧上只保存对象实例和数组的引用。
  • 在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾回收时才有可能被移除。堆上的数据是线程共享的,本线程用完后,无法确定其他线程是否还是使用(要确定其他线程是否在使用代价较高)。因此需要等到离线 任务(垃圾回收)去执行这个耗时较长的确认过程。
  • 堆是 GC(Garbage Collection,垃圾收集器)执行垃圾回收的重点区域。由于 Method Area 和 Heap Area 内存没有过期策略,所以才诞生类 GC。Heap Area 数据变化比 Method Area 更加剧烈,有用户线程创建很多数据,因此也可以 GC就是为 Heap Area 而生的。

在下图在与到 new、newarray、anewarray 指令时就会在堆中开辟空间创建对象。

内存细分

现代大部分垃圾收集器都是基于分代收集理论设计的。

Java 7 之前堆内存逻辑划分为:

  • 新生区(Young Generation Space): Young/New
  • 养老区(Tenure generation Space):Old/Tenure
  • 永久区(Permanent Space):Perm

Java 8 之前堆内存逻辑划分为:

  • 新生区(Young Generation Space): Young/New
    • 又被划分为 Eden 区和 Survivor 区
  • 养老区(Tenure generation Space):Old/Tenure
  • 元空间(Meta Space):Mate

约定:

  • 新生区 ⇔\Leftrightarrow 新生代 ⇔\Leftrightarrow 年轻代
  • 养老区 ⇔\Leftrightarrow 老年区 ⇔\Leftrightarrow 老年代
  • 永久区 ⇔\Leftrightarrow 永久代

堆空间内部结构(JDK 7)

如下图:我们限制 JVM 的栈空间为 10 M,通过下图可以看到:

  • 伊甸园:2 M
  • S0区:0.5 M
  • S1区:0.5 M
  • 老年代:7 M

一共 10 M

    public static void main(String[] args) {
   
   
        System.out.println("start...");
        try {
   
   
            Thread.sleep(1000000);
        } catch (Exception e) {
   
   
            e.printStackTrace();
        }
        System.out.println("end...");
    }

设置堆内存大小与 OOM

设置堆内存大小的参数

  • “-Xms”:用于表示堆区的起始内存,等价于-XX:InitialHeapSize。-X:是 JVM 的运行参数。ms:memory start
  • “-Xmx”:用于表示堆区的最大内存,等价于-XX:MaxHeapSize。

一旦堆区中内存大小超过 “-Xmx” 所指定的最大内存是,将会抛出 OutOfMemoryError 异常。

通常 会将 -Xms 和 -Xmx 两个参数配置相同的值,其目的是为了能够在 Java 垃圾回收机制清理完堆区后不需要重新分割计算堆区的大小,从而提供性能。

默认情况下,

  • 初始内存大小:电脑物理内存大小 / 64
  • 最大内存大小:电脑物理内存大小 / 4
    public static void main(String[] args) {
   
   
        // 返回 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");

        System.out.println("系统内存大小为:" + initialMemory * 64.0 / 1024 + "G");
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值