深入元空间

元空间是干嘛的?

元空间存储的是类的相关信息,就是类的运行时表达。包括:

  1. Class文件

  1. 类的结构和方法

  1. 常量

  1. 注解

  1. 代码优化

JDK1.8分界

在1.8版本之前,类的meta信息、类变量、字符串常量池都存储在永久代。(这里的永久代可以视为方法区)

1.8版本以后,类变量、实例变量、字符串常量池都在堆,meta放到了元空间(这里的元空间可以视为方法区)

元空间上的内存分配

类首次使用的时候,由类加载器锁定Class文件的位置,并在元空间分配内存。类加载器是在堆内存上的,但是元空间的内存是归属于这个类加载器对象的。后续再使用同一类型,不再分配新的元空间内存了,因为使用的Class是同一个。

bootstrap类加载器和application类加载器是不会被回收的,而动态类加载器,在其负责加载的类对象不再使用时会被回收。

元空间的内存大小

元空间的内存大小,默认和本地内存大小一样。但是可以通过-XX:MetaspaceSize指定元空间的内存大小。

元空间在以下两种情况下会触发垃圾回收:

  1. OOM发生

  1. 元空间的内存占用超过了JVM的阈值

默认阈值的大小就是-XX:MetaspaceSize,可以通过-XX:MinMetaspaceFreeRatio和-XX:MaxMetaspaceFreeRatio来指定。

元空间内存回收

元空间分配的内存回收的前提是对应的类加载器不再使用。

类加载器被回收的前提是,这个类加载器负责的相关类的实例不再使用。

此时,存在两个类型为O的对象,一个类型为P的对象,对应的类加载器的实例是深蓝色的那个圆。元空间中分配了相关空间给O和P类存储相关信息。

如果两个O类型的对象不再使用,此时两个实例不再对应栈上的任何引用,但是尚未进行垃圾回收。

完成一次垃圾回收,此时O类型的两个对象已被清理,剩下的P类型的对象和类加载器的实例一起被复制到了Survivor区域。但是,此处虽然O类型不再使用,但是对应的元空间的内存占用不能被释放,因为这个类加载器,不仅仅负责O类型,还负责P类型,而P类型还存在实例,因此不可以被回收。

最终,P对象也被释放,meta空间也完成了释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值