当前位置: 首页 > news >正文

方法区和元空间有什么关系?

一.什么是方法区?

方法区属于是 JVM 运行时数据区域的一块逻辑区域,是各个线程共享的内存区域。

《Java 虚拟机规范》只是规定了有方法区这么个概念和它的作用,方法区到底要如何实现那就是虚拟机自己要考虑的事情了。也就是说,在不同的虚拟机实现上,方法区的实现是不同的。

当虚拟机要使用一个类时,它需要读取并解析 Class 文件获取相关信息,再将信息存入到方法区。方法区会存储已被虚拟机加载的 类信息、字段信息、方法信息、常量、静态变量、即时编译器编译后的代码缓存等数据

二.方法区和永久代以及元空间有什么关系?

  • Jdk1.6及之前,有永久代(Permenent generation),静态变量存放在永久代上
  • Jdk1.7有永久代,但已经逐步"去永久代",字符串常量池,静态变量移除保存在堆上
  • Jdk1.8及之后,没有永久代,类型信息,字段,方法,常量保存在本地内存的元空间中,但是字符串常量池,静态变量仍在堆中.

方法区和永久代以及元空间的关系很像 Java 中接口和类的关系,类实现了接口,这里的类就可以看作是永久代和元空间,接口可以看作是方法区,也就是说永久代以及元空间是 HotSpot 虚拟机对虚拟机规范中方法区的两种实现方式。
在这里插入图片描述

三.为什么要将永久代 (PermGen) 替换为元空间 (MetaSpace) 呢?

在这里插入图片描述
1、整个永久代有一个 JVM 本身设置的固定大小上限,无法进行调整,而元空间使用的是直接内存,受本机可用内存的限制,虽然元空间仍旧可能溢出,但是比原来出现的几率会更小。
你可以使用 -XX:MaxMetaspaceSize 标志设置最大元空间大小,默认值为 unlimited,这意味着它只受系统内存的限制。-XX:MetaspaceSize 调整标志定义元空间的初始大小如果未指定此标志,则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。

2、元空间里面存放的是类的元数据,这样加载多少类的元数据就不由 MaxPermSize 控制了, 而由系统的实际可用空间来控制,这样能加载的类就更多了。

3、在 JDK8,合并 HotSpot 和 JRockit 的代码时, JRockit 从来没有一个叫永久代的东西, 合并之后就没有必要额外的设置这么一个永久代的地方了。

四.什么是运行时常量池?

Class 文件中除了有类的版本、字段、方法、接口等描述信息外,还有用于存放编译期生成的各种字面量(Literal)和符号引用(Symbolic Reference)的常量池表(Constant Pool Table)。常量池表会在类加载后存放到方法区的运行时常量池中。

字面量是源代码中的固定值的表示法,即通过字面我们就能知道其值的含义。字面量包括整数、浮点数和字符串字面量,符号引用包括类符号引用、字段符号引用、方法符号引用和接口方法符号引用。

运行时常量池的功能类似于传统编程语言的符号表,尽管它包含了比典型符号表更广泛的数据。

既然运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申请到内存时会抛出 OutOfMemoryError 错误。

JDK1.7 及之后版本的 JVM 已经将运行时常量池从方法区中移了出来,在 Java 堆(Heap)中开辟了一块区域存放运行时常量池。

五.字符串常量池有什么作用?

字符串常量池 是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建.

String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
System.out.println(aa==bb);// true

JDK1.7 之前运行时常量池逻辑包含字符串常量池存放在方法区。JDK1.7 的时候,字符串常量池被从方法区拿到了堆中。

这里的字符串其实就是我们前面提到的字符串字面量。在声明一个字符串字面量时,如果字符串常量池中能够找到该字符串字面量,则直接返回该引用。如果找不到的话,则在常量池中创建该字符串字面量的对象并返回其引用。

六.JDK 1.7 为什么要将字符串常量池移动到堆中?

主要是因为永久代(方法区实现)的 GC 回收效率太低,只有在整堆收集 (Full GC)的时候才会被执行 GC。Java 程序中通常会有大量的被创建的字符串等待回收,将字符串常量池放到堆中,能够更高效及时地回收字符串内存。

总结

一张图片带你看看 JDK1.6 到 JDK1.8 方法区的变化。
在这里插入图片描述

http://www.lryc.cn/news/12508.html

相关文章:

  • 2023VNCTF的两道(暂时)
  • JDK版本区别
  • Android 基础知识4-2.8 TableLayout(表格布局)详解
  • SQL代码编码原则和规范
  • 【博客627】gobgp服务无损变更:graceful restart特性
  • 一起学 pixijs(1):常见图形的绘制
  • 2023年PMP考试教材有哪些?(含pmp资料)
  • centos7防火墙工具firewall-cmd使用
  • js html过滤所有标签格式并清除所有nbsp;
  • 「技术选型」深度学习软件如何选择?
  • 加油站会员管理小程序实战开发教程13
  • Go语言Web入门之浅谈Gin框架
  • 《MySQL学习》 MySQL优化器选择如何选择索引
  • uniapp 悬浮窗(应用内、无需授权) Ba-FloatWindow2
  • MMKV与mmap:全方位解析
  • 【信息系统项目管理师】项目管理十大知识领域记忆敲出(整体范围进度)
  • 一起学 pixijs(3):Sprite
  • 深入讲解Kubernetes架构-垃圾收集
  • Flink03: 集群安装部署
  • OCR项目实战(一):手写汉语拼音识别(Pytorch版)
  • 【js】export default也在影响项目性能呢
  • 《软件安全》 彭国军 阅读总结
  • 深入讲解Kubernetes架构-节点与控制面之间的通信
  • 120个IT冷知识,看完就不愁做选择题了
  • Java之动态规划之机器人移动
  • seata源码-全局事务提交 服务端源码
  • C++ 模板
  • JWT安全漏洞以及常见攻击方式
  • 华为OD机试题 - 最小施肥机能效(JavaScript)
  • Python(1)变量的命名规则