JDK1.7和JDK1.8的内存模型比较

由于网上文章态鱼龙混杂,完全不知道哪个是对的,在查阅资料以及翻阅很多文章后做一个自己认为是对的总结,如有错误请您指出来,谢谢

JDK1.7内存模型

对于这五个区域我大概做一个大概介绍,详细情况可以查阅其他资料或者文章

程序计数器:线程私有,可以看做当前程序执行的行号指令器。

Java虚拟机栈:线程私有,生命周期与线程相同,虚拟机栈描述的是Java方法执行的内存模型,每个方法在执行时会形成一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,一个方法从调用到执行完毕,就是一个栈帧从进栈到出栈的过程,下图是虚拟机栈的结构模型,图片来源和详细解释:https://www.cnblogs.com/aflyun/p/10575740.html

 本地方法栈:线程私有,作用于Java虚拟机栈类似,只不过Java虚拟机栈执行Java方法,而本地方法栈运行本地的Native方法。

:Java虚拟机管理的最大的一块内存区域,Java堆是线程共享的,用于存放对象实例。也就是说对象的出生和回收都是在这个区域进行的。堆分为初生代(Young Gen)和老年代(Tenured Gen),比例默认为1:2,而初生代又分为Eden和From和To三个区域,比例默认为8:1:1,如下图

方法区:线程共享,用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,这里要说一下方法区和永久代到底是什么关系,永久代是HotSpot虚拟机对于方法区的实现,方法区的实现是不受虚拟机规范约束的,这里只是HotSpot虚拟机团队是这样实现的。

运行时常量池:在JDK1.7中,是运行时常量池是方法区的一部分,用于存放编译期生成的各种字符变量和符号引用。其实除了运行时常量池,还有字符串常量池,class常量池,具体的介绍和区别请看这篇文章:Java中的常量池(字符串常量池、class常量池和运行时常量池)

以上就是JDK1.7的虚拟机内存模型。

JDK1.8内存模型

JDK1.8与1.7最大的区别是1.8将永久代取消,取而代之的是元空间,既然方法区是由永久代实现的,取消了永久代,那么方法区由谁来实现呢,在1.8中方法区是由元空间来实现,所以原来属于方法区的运行时常量池就属于元空间了。元空间属于本地内存,所以元空间的大小仅受本地内存限制,但是可以通过-XX:MaxMetaspaceSize进行增长上限的最大值设置,默认值为4G,元空间的初始空间大小可以通过-XX:MetaspaceSize进行设置,默认值为20.8M,还有一些其他参数可以进行设置,元空间大小会自动进行调整,详细请看这篇文章:jdk8 Metaspace 调优

这里要说明一下,要区分字符串常量池和运行时常量池,这里引用这篇文章JDK1.8关于运行时常量池, 字符串常量池的要点所提到的:

  •  在JDK1.7之前运行时常量池逻辑包含字符串常量池存放在方法区, 此时hotspot虚拟机对方法区的实现为永久代
  • 在JDK1.7 字符串常量池被从方法区拿到了堆中, 这里没有提到运行时常量池,也就是说字符串常量池被单独拿到堆,运行时常量池剩下的东西还在方法区, 也就是hotspot中的永久代
  • 在JDK1.8 hotspot移除了永久代用元空间(Metaspace)取而代之, 这时候字符串常量池还在堆, 运行时常量池还在方法区, 只不过方法区的实现从永久代变成了元空间(Metaspace) 

参考文献:

https://blog.csdn.net/bruce128/article/details/79357870

https://www.cnblogs.com/aflyun/p/10575740.html

https://blog.csdn.net/q5706503/article/details/84640762

https://blog.csdn.net/zm13007310400/article/details/77534349

《深入理解Java虚拟机

猜你喜欢

转载自blog.csdn.net/Hollake/article/details/92762180