Java中的新生代、老年代、永久代和各种GC

Java中的新生代、老年代、永久代和各种GC

转载自: 《JVM的新生代、老年代、MinorGC、MajorGC》

JVM中的堆,一般分为三大部分:新生代、老年代、永久代:

1 新生代

主要是用来存放新生的对象。一般占据堆的1/3空间。由于频繁创建对象,所以新生代会频繁触发MinorGC进行垃圾回收。

新生代又分为 Eden区、ServivorFrom、ServivorTo三个区。

  • Eden区:Java新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当Eden区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。
  • ServivorTo:保留了一次MinorGC过程中的幸存者。
  • ServivorFrom:上一次GC的幸存者,作为这一次GC的被扫描者。

当JVM无法为新建对象分配内存空间的时候(Eden满了),Minor GC被触发。因此新生代空间占用率越高,Minor GC越频繁。

MinorGC的过程:采用复制算法。

  1. 首先,把Eden和ServivorFrom区域中存活的对象复制到ServicorTo区域(如果有对象的年龄以及达到了老年的标准,一般是15,则赋值到老年代区)
  2. 同时把这些对象的年龄+1(如果ServicorTo不够位置了就放到老年区)
  3. 然后,清空Eden和ServicorFrom中的对象;最后,ServicorTo和ServicorFrom互换,原ServicorTo成为下一次GC时的ServicorFrom区。

2 老年代

老年代的对象比较稳定,所以MajorGC不会频繁执行。

在进行MajorGC前一般都先进行了一次MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。当无法找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次MajorGC进行垃圾回收腾出空间。

MajorGC采用标记—清除算法:

  1. 首先扫描一次所有老年代,标记出存活的对象
  2. 然后回收没有标记的对象。

MajorGC的耗时比较长,因为要扫描再回收。MajorGC会产生内存碎片,为了减少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。

当老年代也满了装不下的时候,就会抛出OOM(Out of Memory)异常。

3 永久代

指内存的永久保存区域,主要存放Class和Meta(元数据)的信息。

Class在被加载的时候被放入永久区域。它和和存放实例的区域不同,GC不会在主程序运行期对永久区域进行清理。所以这也导致了永久代的区域会随着加载的Class的增多而胀满,最终抛出OOM异常。

在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。

元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入 native memory, 字符串池和类的静态变量放入java堆中. 这样可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制。

  • Major GC和Full GC区别
  • Full GC:收集young gen、old gen、perm gen
  • Major GC:有时又叫old gc,只收集old gen
### 使用 `jstat` 命令查看 Java 应用程序的新生代年代GC 详情 #### 查看内存占用垃圾回收统计信息 为了获取关于Java虚拟机(JVM)中的新生代年代以及永久(PermGen)/元空间(Metaspace)的信息,可以使用`jstat -gcutil <pid>`命令来监控不同区域的空间利用率及其变化趋势[^1]。 此命令会输出一系列列数据表示各个部分占总容量的比例: - **S0**: Survivor Space 0 的使用率。 - **S1**: Survivor Space 1 的使用率。 - **E** : Eden Space 的使用率。 - **O (Old)**: 年区的年代使用比例。 - **M (Metaspace)** 或者 P(Perm): 如果是 JDK8 及以上版本,则显示 Metaspace;如果是更早版本则为 Perm Gen。 - **YGC/YCT/FGC/FCT/TGCT**: 年轻收集次数,年轻收集耗时,完全收集次数, 完全收集耗时 总的垃圾收集时间. 对于定期采样分析而言,可以通过指定间隔时间重复次数参数来进行连续监测。例如:`jstat -gcutil PID 1000 5`,这将在每秒打印一次统计数据共五次[^2]. ```bash $ jstat -gcutil <PID> 1000 5 S0 S1 E O M CCS YGC YGCT FGC FGCT GCT 0.00 0.00 76.94 32.91 97.67 97.67 13 0.134 2 0.261 0.395 ... ``` #### 获取详细的内存分配配置 如果想要了解具体的内存分配细节,比如各的最大最小尺寸等,应该采用如下形式调用工具: ```bash jstat -gccapacity <PID> ``` 这条指令能够提供有关初始容量(`ICAP`)、已提交容量(`CCSMX`)、最大可能扩展到的大小(`MC`,`OC`,`PC`)等方面的数据,有助于评估是否存在潜在的 OutOfMemoryError 风险并调整相应的 JVM 参数设置. 通过上述两种方式结合实际运行状况下的日志记录,可以帮助开发人员快速定位性能瓶颈所在之处,并采取适当措施优化应用程序的表现.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值