解密 JMV 内存区域 堆

本文详细介绍了JVM堆内存的结构,包括新生代、老年代和永久代(JDK1.8后变为元空间)。堆是JVM中最大的内存区域,用于对象存储,其大小可通过JVM参数调节。现代垃圾回收器基于分代收集理论,新生代包括伊甸园和幸存区,老年代则存放长期存活的对象。文章还探讨了堆内存分配、垃圾收集算法以及如何避免内存溢出(OOM)问题。此外,提到了对象创建过程、逃逸分析和标量替换,指出在特定条件下,对象可以不在堆上分配内存。
摘要由CSDN通过智能技术生成

堆是JVM中相当核心的内容,因为堆是JVM中管理的最大一块内存区域,大部分的GC也发生在堆区,那接下来就让我们深入地探究一下JVM中的堆结构。

需要明确,一个JVM实例只存在一个堆内存,堆区在JVM启动的时候就被创建,其空间大小也被确定下来,但堆空间的大小是可以通过JVM参数调节的,所有的线程共享堆。

堆的内存结构

因为堆是垃圾回收的重点区域,现代垃圾回收器大部分都基于分代收集理论设计,所以将堆空间分为:

  1. Young Generation Space(新生代)

  2. Old Generation Space(老年代)

  3. Perm Space(永久代)- 永久代是方法区的一个实现(只有HotSpot JVM才有永久代),事实上方法区是逻辑独立的,即:从逻辑上来说,方法区是在堆的外面的

其中新生代又可细分为:

  1. Eden(伊甸园区)

  2. Survivor(幸存区)

从JDK1.8开始,JVM规范摒弃了方法区的概念,取而代之的是Meta Space(元空间),使用的是物理内

存。

通过两个JVM参数可以设置堆的初始内存和最大内存:

  • -Xms:设置堆的初始内存

  • -Xmx:设置堆的最大内存

我们可以先来看看自己的JVM分配的堆内存情况:

public static void main(String[] args) {
    // 获取堆空间的内存总量
    long totalMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
    // 获取堆空间试图使用的最大内存
    long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;
    System.out.println(totalMemory + "M");
    System.out.println(maxMemory + "M");
}

运行结果:

123M
1799M

默认情况下堆的初始内存大小是物理内存的64分之一,而最大内存大小是物理内存的四分之一,但是会发现,物理内存(8G)的四分之一应该是2G才对,而堆的最大内存空间并没有到达2G,这个问题我们留到后面解决,先来设置一下堆的内存大小:

在VM options中填入 -Xms600m -Xmx600m ,若是找不到VM options,则点击右上角的Modify options,并勾选Add VM options,此时重新运行程序,结果为:

575M
575M

接下来我们来详细地分析一下堆的内存分配情况,打开cmd窗口,输入 jps 指令可以查看当前正在运行的Java程序,所以改造一下刚才的程序:

public static void main(String[] args) {
    while (true){

    }
}

一直让它运行着,然后输入 jps :

C:\Users\Administrator>jps
1860 TestDemo
10664 Jps
2568 Launcher
8200

这样便查询到了TestDemo程序的进程id,然后通过该id查询内存分配情况,输入 jstat -gc 1860 ÿ

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值