JVM笔记(5)—— 运行时数据区—— 方法区

上一篇:JVM笔记(4)—— 运行时数据区——堆空间

一、栈、堆、方法区的交互关系

进程运行过程中,在方法中创建对象时通过方法区中的类型信息在堆中创建对应的对象,对象中又存有指向方法区中对应类型信息的指针,并将对象的地址引用存入虚拟机栈对应方法栈帧的局部变量表中。
在这里插入图片描述

二、方法区的理解

方法区是所有线程共享的区域,主要用于存储类加载系统加载进来的每个类的类信息,JIT即时编译器编译后的代码缓存等

在这里插入图片描述

jdk7及以前,方法区的实现称为永久代(PermGen space),8及以后则称为元空间(Metaspace)。
元空间与永久代的最大区别在于: 元空间不在虚拟机设置的内存中,而是直接使用本地内存 \color{red}{元空间不在虚拟机设置的内存中,而是直接使用本地内存} 元空间不在虚拟机设置的内存中,而是直接使用本地内存。因此更不容易出现OOM

三、设置方法区大小与OOM

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

四、方法区的内部结构

方法区主要存储类加载系统加载进来的每个类的类信息等,而方法区中一个类的类信息又包括类型信息、域信息、方法信息、运行时常量池四个部分。

1. 类信息

类型信息

在这里插入图片描述

域信息

也称为类的属性信息,类的域包括实例变量、类变量、类常量,域信息中要存储每个域的域名称、域类型、域修饰符,并且要存储这些域定义的顺序。

在这里插入图片描述

注意:jdk1.7及以后字符串常量池和类的静态变量被放到了堆中

方法信息

在这里插入图片描述

运行时常量池

在一个类的代码中有各种字面量(如字符串、数值等)或者其他类和方法,这些很长的字面量或者符号不可能直接写在字节码指令中,因此编译后在字节码文件中是用一个常量池来存储的,这样可以对符号重复利用,在字节码指令中直接用常量池索引来表示即可(例如字节码指令invokevirtual #3,表示执行索引#3存储的符号引用指向的方法)。常量池中包括各种字面量和对类型、域和方法的符号引用。

类的字节码文件加载到方法区后常量池即被转化为运行时常量池,其中对类型、域和方法的符号引用会转换为进程中其真实的地址。

在这里插入图片描述

五、方法区的演进细节

版本演进
jdk6方法区实现为永久代,字符串常量池StringTable和类的静态变量存储在方法区中
jdk7方法区实现为永久代,字符串常量池StringTable和类的静态变量转移到了堆中
jdk8方法区实现为元空间,并且方法区从虚拟机内存转移到了本地内存

注意这里指的是静态变量的引用,其所指向的对象始终都是在堆中

在这里插入图片描述

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

字符串常量池StringTable为什么要调整位置?

前置知识:

  1. 什么是字符串常量池?
  2. 深入浅出java常量池和基本数据类型对象池

在这里插入图片描述

六、方法区的垃圾收集

方法区垃圾收集主要回收两部分内容:常量池中不被引用的常量,不再被使用的类

在这里插入图片描述

七、运行时数据区总结

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值