Java进程中的堆和栈_对于JVM,你就只知道堆和栈吗?

不少java程序员一提JVM运行时数据区域,就会说堆和栈,当然也有java程序员给出方法区、虚拟机栈、本地方法栈、堆、程序计数器这个答案,但是还有人给出永久代、虚拟机栈、本地方法栈、堆、程序计数器这个答案。那么究竟哪种答案是正确的呢?

首先我们介绍两个概念,这对于我们回答上面的问题来说是必不可少的。

1.虚拟机: 简单的说虚拟机是一种抽象的计算机。

2.Java虚拟机规范: 虚拟机规范是一种对Java虚拟机的约束,Java虚拟机负责对虚拟机规范进行实现。

我们平常所说JAVA虚拟机一般是指的一种具体的JAVA虚拟机规范的实现,比如说HotSpot。当然市面上还有其他的Java虚拟机。

下面的截图内容来自https://docs.oracle.com/javas...

a5b07dc770591b80cf452f2906c88812.png

从JVM6规范,我们可以看到,规范要求的运行时数据区域有: PC Register(程序计数器)、Java Virtual Machine Stacks(java 虚拟机栈)、Heap(堆)、Method Area(方法区)、Native Method Stacks(本地方法栈)、Runtime Constant Pool(运行时常量池这及部分)。

注意标红部分,我们可以看到运行时常量池位于方法区内。

根据规范我们可以大概的画出JVM运行实数据区域(执行引擎、本地库接口在后面的文章中会进行详细介绍)。

031632ce1092f52494121a07bd11f47e.png

在认真的看完JVM6、7、8的运行时数据区域规范之后,JVM6、7、8关于对运行时的数据区域要求一点变化都没有,还是程序计数器、Java虚拟栈、堆、方法区、本地方法栈、运行时常量池这几个部分。

那永久代是方法区的别名咯,准确的说是方法区的实现。规范是这么要求的,但是虚拟机会对这些区域进行调整,或者说是调整对JVM规范的实现。

查找了很多资料以后,还是没有找到官方对于永久代的描述(有找到官方文档关于永久代(Permanent Generation)的描述的,请联系我)。综合了很多博客和一些资料之后,我们可以做出如下判断,永久代是HotSpot虚拟机特有的概念,HotSpot团队使用永久代来实现JVM规范中的方法区。对于其他虚拟机来说是不存在永久代这个概念的。jdk8移除了永久代,关于这点我们将在后文进行详细的介绍。

那么为什么称方法区为永久代呢?

这跟GC分代收集有一定的关系,内存回收发生在方法区和堆中。

我们使用-XX:+PrintGCDetails参数,在IDEA中查看堆中的信息。

2e5d7585050a2517af9ad598d5e012e1.png

注意到PSYoungGen和ParOldGen这两个单词,从控制台的信息我们可以看出堆中的区域划分

PSYoungGen

eden space

from space

to space

ParOldGen

PS和Par代表垃圾回收器

也就是说堆里面又可以再分为年轻代、老年代,堆是垃圾回收机制的重点区域,将方法区也纳入垃圾回收范围,与年轻代、老年代相对,称方法区为永久代。

这就是永久代的来历。

接下来介绍一下JVM1.7和1.6的不同。

在介绍JVM1.6和1.7的区别之前,我们先介绍String类的intern()方法

字符串在调用该方法的时候,如果字符串常量池里面还没有该字符串,则将该字符串添加进字符串常量池中。

查了一下,还是没有查到HotSpot官方对于运行时数据区域的说明,但是许多博客都指出jdk1.7将字符串常量池移动到了堆中。

以下是分别在1.6、1.8的测试例子

07fa366cb9d5a1e5b19843cf3b33e218.png

1.6结果: false

1.7以上的结果:true

我们来解释一下原因,1.6中字符串常量池放在永久代中和堆是隔离的。

我们来画个图来解释一下,

1.6

2505dfd4ce83512fd50755414b5c1729.png

1.7的虚拟机做了调整,常量池中不需要在存储一份对象了,可以存储堆中的引用,更为灵活。

1.7及以上的图

55063b9f49503234e31cce4534cc1207.png

请看下一张图。

jdk版本在1.8。MetaSpace是什么鬼?

b622a16c1811fb55fb11f9f35c01e26a.png

Jdk1.8移除了永久代或者说用MetaSpace去实现虚拟机规范中的方法区。

详见:JEP 122: Remove the Permanent Generation

我查了很多资料,还是没有找到官方对MetaSpace的解释和描述,到是在深入探究 JVM | 探秘 Metaspace这篇博客中看到了MetaSpace的相关描述。

In JDK 8, classes metadata is now stored in the native heap and this space is called Metaspace.

字符串常量池仍然在堆中,方法区移动至MetaSpace中

那么如果有人问你JVM运行时区域由几部分组成,那么应该如何回答呢?

我认为答案可以是这样的:JVM规范中的要求JVM运行时区域有以下及部分:

方法区

java虚拟机栈

本地方法栈

程序计数器

运行时常量池(位于方法区中)

但是不同的虚拟机对规范有着不同的实现,HotSpot1.6对方法区的实现叫永久代,1.7将字符串常量池移动到了堆中,1.8移除了永久代改用元数据区实现方法区,字符串常量池仍然在堆中。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值