《Yangzai的知识地图》-jvm运行时数据区及永久代消失之谜

0、个人的一点理解

Java虚拟机规范将运行时数据区进行划分的目的就是为了更好的加载类并将类中的数据进行分配,然后便于运行时的使用这是其一,其二,为了便于垃圾回收时更好的回收。

1、区域就这么几块

这里是引用

  • 翻译一下就是:

1.1、PC寄存器

Java虚拟机可以支持多条线程同时执行,,每一个线程都有自己的PC寄存器,任意时刻一个虚拟机线程只会执行一个方法代码,这个正在被线程执行的方法称为该线程的当前方法【current method】。如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地
址;如果正在执行的是本地(Native)方法,这个计数器值则应为空(Undefined)。

1.2、Java虚拟机栈

Java虚拟机都会同步创建一个栈帧[1](Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

1.3、本地方法栈

本地方法栈(Native Method Stacks)与虚拟机栈所发挥的作用是非常相似的,其区别只是虚拟机
栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的本地(Native)
方法服务。

1.4、Java堆

供所有类实例和数组对象分配内存的区域。

1.5、方法区

用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

1.6、运行时常量池

运行时常量池(Runtime Constant Pool)是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表(Constant Pool Table),用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

  • 更详细的资料可以参考《Java虚拟机规范,Java SE 8版》和《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》也可以关注公众号👉 YangzaiLeHeHe 【回复 1 】或者 添加我的微信Yang_sir_xu
2、总结一下

运行时常量池是在方法区中的,为了更好的管理,所以方法区即使是堆的一部分,但是为了逻辑上的区分划分为Java堆和方法区,PC寄存器、虚拟机栈、本地方法栈是随着线程的创建而创建的共生共灭;方法区、堆是随着虚拟机的启动而创建的。

2、面试中常说的永久代不见了,是咋回事呢?

2.1、垃圾回收

前面提到过这么分区有一部分是为了垃圾回收的,那么虚拟机规范中也没有提到什么所谓的永久代,所以 首先得明白 永久代不是虚拟机规范的一部分,它只是Hotspot虚拟机对于虚拟机规范实现时用永久代实现了方法区,Hotspot虚拟机垃圾分代回收时会有永久代的分法。

2.2、Java1.7到Java1.8的差异->消失的永久代

Oracle官网文章可以先看一下

通过这篇文章我们知道了的确是没有永久代了。那么另外一个问题就呼之欲出了:为什么元数据区取代了永久代?这话谁说的?为啥这么说?他说的对吗?我有很多❓❓❓❓❓❓❓❓❓,你有吗?
在这里插入图片描述
还有常量池去哪了?一会说在这一会说在那,我都懵逼了,年轻人我劝你耗子尾汁👀

2.3、继续了解

  • 证据1

The proposed implementation will allocate class meta-data in native memory and move interned Strings and class statics to the Java heap. Hotspot will explicitly allocate and free the native memory for the class meta-data. Allocation of new class meta-data would be limited by the amount of available native memory rather than fixed by the value of -XX:MaxPermSize, whether the default or specified on the command line.

被提议的实现将在本机内存中分配类元数据【class meta-data】将内部字符串和类静态移动到Java堆中.Hotspot将明确的为类元数据分配和释放本机内存。新类元数据的分配将受到本地可用内存量的限制,而不是由-XX:MaxPermSize值(不管是默认值还是在命令行中指定的值)来固定。

  • 2证据2

Success Metrics
Class metadata, interned Strings and class static variables will be moved from the permanent generation to either the Java heap or native memory.
The code for the permanent generation in the Hotspot JVM will be removed.
Application startup and footprint will not regress more than 1% as measured by a yet-to-be-chosen set of benchmarks.

类元数据、内部字符串和类静态变量将从永久生成移动到Java堆或本机内存中。

2.3.1、结论

1、永久代真的不在了,但是 方法区还在的。
2、类元数据被放在了元数据区,内部字符串和类静态变量放在了Java堆中【我认为这就是方法区】。换个说法:类元数据被放在了元数据区,内部字符串和类静态变量放方法区

2.3.2、细思极爽

为啥将类元数据放在元数据区?
以前用永久代的时候【也就是方法区】因为方法区可以放类的结构信息,常量和静态变量,而在Hotspot在使用永久代实现方法区的时候,永久代会有默认的大小受-XX:MaxPermSize控制,如果一个应用加载的类过多那么很有可能达到阈值,而现在将类元数据移动到元数据区直接使用本地内存来管理,该区域的上限就是本机内存的上限,并且上文也提到了Hotspot会明确的为类元数据分配和释放本机内存。此外以前的永久代即方法区还会存放常量等,那么如果发生了FullGC的时候会将永久代中的常量也回收,那么在使用String.intern()【关于intern()可以参考另一篇文章】的方法时就会因永久代的原因而导致不同虚拟机下有不同的表现。
在这里插入图片描述

3、我看的所谓一手资料😂

0、Oracle官网虚拟机规范列表
1、Java虚拟机规范,Java SE 14版
2、Java虚拟机规范,Java SE 8版
3、官网关于删除永久代的描述文章

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值