文档章节

面试官,Java8 JVM内存结构变了,永久代到元空间

程序新视界
 程序新视界
发布于 10/22 11:59
字数 1924
阅读 55
收藏 0

在文章《JVM之内存结构详解》中我们描述了Java7以前的JVM内存结构,但在Java8和以后版本中JVM的内存结构慢慢发生了变化。作为面试官如果你还不知道,那么面试过程中是不是有些露怯?作为面试者,如果知晓这些变化,又将成为面试中的亮点。

如果在网络上搜索JVM内存结构,90%的可能会搜到Java7及以前的内存图,本篇文章将会对JVM内存结构再次细化,深入理解Java8之后的内部变化。现在意识到关注公众号“程序新视界”的好处了吧。在这里可以不断的刷新你的知识和认知。

JVM内存结构的细化

再来看一下《JVM之内存结构详解》中的内存结构图。

jvm内存结构

为了更细化的讲解,我们将该图进行进一步的优化调整。针对java7及以前版本的细化。

jvm内存结构

看出变化了吗?堆和方法区连在了一起,但这并不能说堆和方法区是一起的,它们在逻辑上依旧是分开的。但在物理上来说,它们又是连续的一块内存。也就是说,方法区和前面讲到的Eden和老年代是连续的。

jvm内存结构

在继续进行下去之前,我们先来理解两个概念:规范和实现。

规范和实现

针对Java虚拟机的实现有专门的《Java虚拟机规范》,在遵守规范的前提下,不同的厂商会对虚拟机进行不同的实现。 就好比开发的过程中定义了接口,具体的接口实现大家可以根据不同的业务需求进行实现。

PS:大家都有必要了解一下《Java虚拟机规范》,关注公众号“程序新视界”,回复“002”获得Java SE 7的虚拟机规范PDF版。

我们通常使用的Java SE都是由Sun JDK和OpenJDK所提供,这也是应用最广泛的版本。而该版本使用的VM就是HotSpot VM。通常情况下,我们所讲的java虚拟机指的就是HotSpot的版本。

永久代(PermGen)

上面理解了规范和实现之后,来看认识一个概念“永久代(Permanet Generation,也称PermGen)”。对于习惯了在HotSpot虚拟机上开发、部署的程序员来说,很多都愿意将方法区称作永久代。

本质上来讲两者并不等价,仅因为Hotspot将GC分代扩展至方法区,或者说使用永久代来实现方法区。在其他虚拟机上是没有永久代的概念的。也就是说方法区是规范,永久代是Hotspot针对该规范进行的实现。

理解上面的概念之后,我们对Java7及以前版本的堆和方法区的构造再进行一下变动。

jvm内存结构

再重复一遍就是对Java7及以前版本的Hotspot中方法区位于永久代中。同时,永久代和堆是相互隔离的,但它们使用的物理内存是连续的。

永久代的垃圾收集是和老年代捆绑在一起的,因此无论谁满了,都会触发永久代和老年代的垃圾收集。

但在Java7中永久代中存储的部分数据已经开始转移到Java Heap或Native Memory中了。比如,符号引用(Symbols)转移到了Native Memory;字符串常量池(interned strings)转移到了Java Heap;类的静态变量(class statics)转移到了Java Heap。

然后,在Java8中,时代变了,Hotspot取消了永久代。永久代真的成了永久的记忆。永久代的参数-XX:PermSize和-XX:MaxPermSize也随之失效。

元空间(Metaspace)

对于Java8,HotSpots取消了永久代,那么是不是就没有方法区了呢?当然不是,方法区只是一个规范,只不过它的实现变了。

在Java8中,元空间(Metaspace)登上舞台,方法区存在于元空间(Metaspace)。同时,元空间不再与堆连续,而且是存在于本地内存(Native memory)。

jvm内存结构

本地内存(Native memory),也称为C-Heap,是供JVM自身进程使用的。当Java Heap空间不足时会触发GC,但Native memory空间不够却不会触发GC。

针对Java8的调整,我们再次对内存结构图进行调整。 jvm内存结构

元空间存在于本地内存,意味着只要本地内存足够,它不会出现像永久代中“java.lang.OutOfMemoryError: PermGen space”这种错误。看上图中的方法区,是不是“膨胀”了。

默认情况下元空间是可以无限使用本地内存的,但为了不让它如此膨胀,JVM同样提供了参数来限制它使用的使用。

  • -XX:MetaspaceSize,class metadata的初始空间配额,以bytes为单位,达到该值就会触发垃圾收集进行类型卸载,同时GC会对该值进行调整:如果释放了大量的空间,就适当的降低该值;如果释放了很少的空间,那么在不超过MaxMetaspaceSize(如果设置了的话),适当的提高该值。
  • -XX:MaxMetaspaceSize,可以为class metadata分配的最大空间。默认是没有限制的。
  • -XX:MinMetaspaceFreeRatio,在GC之后,最小的Metaspace剩余空间容量的百分比,减少为class metadata分配空间导致的垃圾收集。
  • -XX:MaxMetaspaceFreeRatio,在GC之后,最大的Metaspace剩余空间容量的百分比,减少为class metadata释放空间导致的垃圾收集。

永久代为什么被替换了

思考一下,为什么使用元空间替换永久代?

表面上看是为了避免OOM异常。因为通常使用PermSize和MaxPermSize设置永久代的大小就决定了永久代的上限,但是不是总能知道应该设置为多大合适, 如果使用默认值很容易遇到OOM错误。

当使用元空间时,可以加载多少类的元数据就不再由MaxPermSize控制, 而由系统的实际可用空间来控制。

更深层的原因还是要合并HotSpot和JRockit的代码,JRockit从来没有所谓的永久代,也不需要开发运维人员设置永久代的大小,但是运行良好。同时也不用担心运行性能问题了,在覆盖到的测试中, 程序启动和运行速度降低不超过1%,但是这点性能损失换来了更大的安全保障。

小结

经过上面的讲解和演变,是不是对JVM的内存结构有了更深的理解了?可以和面试官多聊一会儿了,毕竟面试官的时间也不多了。另外,走过路过不要错过,该系列持续更新中。最后别忘了关注公众号“程序新视界”获得第一手资料。

原文链接:《面试官,Java8 JVM内存结构变了,永久代到元空间

《面试官》系列文章:


<center><b>程序新视界</b>:精彩和成长都不容错过</center>

程序新视界-微信公众号

© 著作权归作者所有

程序新视界
粉丝 0
博文 57
码字总数 94090
作品 0
东城
私信 提问
java 面试知识点笔记(三)底层知识 jvm 内存模型 下篇

上一篇讲完了java内存模型中线程私有部分(程序计数器、虚拟机栈、本地方法栈),这篇讲下所有线程公有部分 问:元空间(MetaSpace)和永久代(PermGen)的区别? 元空间使用本地内存,而永久代使...

断风格男丶
05/15
26
0
JVM结构 方法区 永久代 元空间

前言 首先明白几个概念:JVM规范和JVM实现,方法区是JVM规范中定义的,永久代是JVM实现(HotSpot)中对于方法区的实现。 Orcale在收到JRockit VM后对JRockit VM和HotSpot的优点做了融合,决定...

Gengry
2017/10/31
48
0
JVM系列第11讲:JVM参数之堆栈空间配置

JVM 中最重要的一部分就是堆空间了,基本上大多数的线上 JVM 问题都是因为堆空间造成的 OutOfMemoryError。因此掌握 JVM 关于堆空间的参数配置对于排查线上问题非常重要。 tips:本文所有配置...

陈树义
2018/12/10
0
0
Java jvm内存调优(来自小强公开课)

Java jvm内存调优 Jdk:java开发工具包 Jre:java运行环境,运行你编写的java程序 Jvm:java虚拟机,.class文件在虚拟机上运行 如何选择合适的java虚拟机 》》》选择稳定的jdk(慎用新出的,...

32氪
2018/06/26
0
0
java永久代,元空间,常量池,方法区详解

1,java内存模型简介 《深入理解java虚拟机》里将java内存分为如下五个模块: 堆-堆是所有线程共享的,主要用来存储对象。 其中,堆可分为:新生代和老年代两块区域。使用NewRatio参数来设定...

Kingram
2018/08/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JS前端MD5加密

Bootstrap官网获得md5 js地址:https://www.bootcdn.cn/blueimp-md5/ <!--MD5加密--><script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.js"></script> 使用方法: md5(pwd)......

被毒打的程序猿_先瑞
14分钟前
4
0
BigDecimal 去后面无用的0的方法

BigDecimal a=new BigDecimal("0.1000"); System.out.println(a.stripTrailingZeros().toPlainString());...

xiaodong16
今天
5
0
JAVA--高级基础开发

[集合版双色球] 十二、双色球规则:双色球每注投注号码由6个红色球号码和1个蓝色球号码组成。红色球号码从1—33中选择;蓝色球号码从1—16中选择;请随机生成一注双色球号码。(要求同色号码...

李文杰-yaya
昨天
20
0
聊聊rocketmq broker的CONSUMER_SEND_MSG_BACK

序 本文主要研究一下rocketmq broker的CONSUMER_SEND_MSG_BACK CONSUMER_SEND_MSG_BACK rocketmq/common/src/main/java/org/apache/rocketmq/common/protocol/RequestCode.java public class......

go4it
昨天
4
0
API常见接口(下)

system类 StringBuilder和StringBuffer 包装类 1.System类 (java.lang包中) 提供了大量的静态方法,可以获取与系统相关的信息或系统级操作。 常用方法: public static long currentTimeMi...

Firefly-
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部