JVM之方法区

本文详细介绍了JVM内存模型中的方法区,包括其历史演变,从JDK7的永久代到JDK8的元空间。方法区主要存储类信息、运行时常量池等,与堆栈交互,存放类变量和静态变量等。JDK1.8将静态变量转移至堆空间,常量池存入元空间,以减少OOM风险并提升IO性能。
摘要由CSDN通过智能技术生成

JVM之方法区

Java虚拟机内存区域模型

**黄色区域:**所有线程共享的内存区域,会存在垃圾回收。

**灰色区域:**线程私有不会产生垃圾回收。

方法区是运行时数据区中的一部分,那么方法区具体的用途是什么呢?方法区能存放什么信息呢?

方法区是什么

方法区和堆一样是被所有的线程所共享,有的地方将方法区称之为Non-Heap(非堆),其目的就是将方法区与堆内存区分开来,在JDK1.7中很多开发者将方法区称之为永久代,但本质上两者并不是等价的,仅仅是因为HotSpot虚拟机的设计团队将GC分代收集扩展至方法区,或者说使用永久代来实现方法区而已,这样HotSpot的垃圾收集器可以像管理堆内存一样管理永久代内存了,其余非HotSpot的虚拟机是没有永久代这个概念的

HotSpot方法区演进

方法区在jdk7及以前,习惯将永久代称之为方法区,结构如下所示

在jdk1.8中采用了Metaspace(元数据空间)替换了Perm(永久区),并且从堆空间分离出来,结构如下所示

一定一定需要注意的是Metaspace(元数据空间)不再存储到堆中,也不使用JVM内存空间而是采用本机的内存,这样元数据只受本地内存大小限制,OOM的问题就不存在了。

为什么JDK1.8需要将方法区从JVM永久代(非直接内存)移到元空间(直接内存)呢?

  • JVM永久代存在容量限制,那么类信息存储的容量有限制容易触发OOM,而采用元空间存储,只受本地内存大小限制OOM的可能性小。

  • 因为是直接内存,JVM将会在IO操作上具有更高的性能,因为它直接作用于本地操作系统的IO操作,而堆内存做IO操作,先需要将数据复制到直接内存,再利用IO处理,而直接内存不需要这层转换。

堆栈和方法区的交互

如我们常常构建的业务对象,以Car对象为例

当我们在代码中创建一个Car实例对象后,将会在堆、栈、方法区内存空间分别写入数据

  • Car:是对象模板,为Class对象,存放在方法区中。

  • car:属于引用数据,存放栈空间中。

  • new Car():需要在堆中开辟一片空间,存放在堆中。

方法区存放什么数据

方法区存放的数据主要是被类加载器加载后的类信息,运行时常量池等等。

其中有两个点需要注意

  • 静态变量,在JDK1.8以前静态变量都是存在永久代内存中,JDK1.8后采用元空间替代永久代,==就将静态变量从永久代转移到了堆空间==。

  • 常量池,在JDK1.7之前运行时常量池逻辑包含了字符串常量池存放在永久代中,JDK1.7将字符串常量池转移到了堆内存中,注意这时并没有提到运行时常量池,也就是说运行时常量池还存在永久代中,JDK1.8将永久代移除用元空间代替,这时运行时常量池就存在元空间中了。

那么类信息又包括什么东西呢?

  • 类信息

  • 类的完整名字

  • 类的直接父类完整名字

  • 类的直接实现接口有序列表

  • 类型标识(是类还是接口)

  • 类的访问修饰符(public、private等等)

  • 类型常量池

  • 存放该类型用到的常量有序集合,包括直接常量(字符串、浮点、整型),和对其它类型、字段、方法的符号引用。

  • 字段信息

  • 字段类型、名称、访问修饰符等

  • 方法信息

  • 类的所有方法

  • 方法返回类型、方法访问修饰符、方法名称等等

  • 类变量

  • 指向类加载器的引用

  • 指向Class实例的引用

  • 方法表

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值