1.4 JVM堆内存

本文详细探讨了Java堆内存的特性和结构,包括新生代与老年代的划分,内存分配与回收机制,以及如何通过-Xms和-Xmx调整堆大小。重点介绍了老年代变迁历史,特别提到了永久代到元空间的转变。此外,还涵盖了堆内存设置和垃圾回收的策略,以及实例分析了内存溢出的可能情况。
摘要由CSDN通过智能技术生成

JVM堆内存

堆内存的特点

  • Java堆(Java Heap)是java虚拟机所管理的内存中最大的一块
  • java堆被所有线程共享的一块内存区域;
  • 虚拟机启动时创建java堆
  • java堆的唯一目的就是存放对象实例
  • java堆是垃圾收集器管理的主要区域
  • 从内存回收的角度来看, 由于现在收集器基本都采用分代收集算法, 所以Java堆可以细分为:新生代(Young)和老年代(Old)。 新生代又被划分为三个区域Eden、From Survivor, To Survivor等。无论怎么划分,最终存储的都是实例对象, 进一步划分的目的是为了更好的回收内存, 或者更快的分配内存。
  • java堆的大小是可扩展的, 通过**-Xmx-Xms**控制。
  • 如果堆内存不够分配实例对象, 并且对也无法在扩展时, 将会抛出outOfMemoryError异常。

堆内存结构

老年代的变迁 别名(非堆

  • jdk1.6 之前: 永久代,常量池在方法区;
  • jdk1.7 :永久代慢慢退化,去永久代,常量池在堆中;
  • jdk1.8 之后:取消永久代,改名为元空间,常量池在元空间中。 元空间使用的是计算机的物理内存 不是JVM内存

**新生代:**Young ,主要用来存放新生的对象。幸存者0区和1区,被轻GC回收后剩下的对象保存区域;

老年代:Old Generation,主要存放应用程序声明周期长的内存对象,被重GC回收后仍旧存在的对象会进入老年代;

永久代:另一个别名为“非堆Non-Heap”,jdk1.8 之后取消永久代,改名为元空间。 元空间使用的是计算机的物理内存 不是JVM内存。主要存放JDK自身携带的Class对象Interface元数据,存储的是java运行时的一些环境或类信息。这个区域不存在垃圾回收关闭JVM虚拟机就会释放这个区域的内存。

如果一个启动类加载了大量的第三方jar包或者Tomcat部署了太多的应用,大量动态生成的反射类,这些有可能造成永久代空间溢出,抛出outOfMemoryError异常。

在这里插入图片描述

堆设置

-Xms :初始堆大小
-Xmx :最大堆大小

-XX:+PrintGCDetails 查看GC回收详情

堆的垃圾回收方式

堆是GC垃圾回收的主要区域。

GC分为两种: Minor GCFull GC(也叫做Major GC).

Minor GC(简称GC)

Minor GC是发生在新生代中的垃圾收集动作, 所采用的是复制算法。
新生代(Young)几乎是所有java对象出生的地方。即java对象申请的内存以及存放都是在这个地方。java中的大部分对象通常不会长久的存活,因此需要垃圾回收。
新生代是收集垃圾的频繁区域。

回收过程如下:

​ 当对象在 Eden ( 包括一个 Survivor 区域,这里假设是 from 区域 ) 出生后,在经过一次 Minor GC 后,如果对象还存活,并且能够被另外一块 Survivor 区域所容纳(上面已经假设为 from 区域,这里应为 to 区域,即 to 区域有足够的内存空间来存储 Eden 和 from 区域中存活的对象 ),则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor 区域 ( 即 to 区域 ) 中,然后清理所使用过的 Eden 以及 Survivor 区域 ( 即 from 区域 ),并且将这些对象的年龄设置为1,以后对象在 Survivor 区每熬过一次 Minor GC,就将对象的年龄 + 1,当对象的年龄达到某个值时 ( 默认是 15 岁,可以通过参数 -XX:MaxTenuringThreshold 来设定 ),这些对象就会成为老年代。
但这也不是一定的,对于一些较大的对象 ( 即需要分配一块较大的连续内存空间 ) 则是直接进入到老年代。

Full GC

Full GC 基本都是整个堆空间及持久代发生了垃圾回收,所采用的是标记-清除算法。
老年代里面的对象几乎个个都是在 Survivor 区域中熬过来的,它们是不会那么容易就 “死掉” 了的。因此,Full GC 发生的次数不会有 Minor GC 那么频繁,并且做一次 Full GC 要比进行一次 Minor GC 的时间更长,一般是Minor GC的 10倍以上。
另外,标记-清除算法收集垃圾的时候会产生许多的内存碎片 ( 即不连续的内存空间 ),此后需要为较大的对象分配内存空间时,若无法找到足够的连续的内存空间,就会提前触发一次 GC 的收集动作

实例分析

​ 比如下面的例子,首先使用GC对新生代的内存进行垃圾回收,在回收几次后,未死亡的对象进入老年代,当老年代内存满了之后,使用Full GC对整个堆内存进行垃圾回收,当新生代和老年代的内存都满了之后,会抛出outOfMemoryError异常,

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值