加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 综合聚焦 > 资源网站 > 空间 > 正文

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

发布时间:2019-10-24 16:11:54 所属栏目:空间 来源:IT技术分享
导读:如果在网络上搜索JVM内存结构,90%的可能会搜到Java7及以前的内存图,本篇文章将会对JVM内存结构再次细化,深入理解Java8之后的内部变化。 再来看一下《 JVM之内存结构详解 》中的内存结构图。 永久代到元空间 src=http://p3.pstatp.com/large/pgc-image/b

如果在网络上搜索JVM内存结构,90%的可能会搜到Java7及以前的内存图,本篇文章将会对JVM内存结构再次细化,深入理解Java8之后的内部变化。

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

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

面试官:Java8 JVM内存结构变了,<span><span><span><i 面试官:Java8 JVM内存结构变了,<span><span><span><i style=永久代到元空间" src="http://p3.pstatp.com/large/pgc-image/b13db3eea8c24ba187d5e5907deb5dd3" _fcksavedurl="http://p3.pstatp.com/large/pgc-image/b13db3eea8c24ba187d5e5907deb5dd3" _fcksavedurl="http://p3.pstatp.com/large/pgc-image/b13db3eea8c24ba187d5e5907deb5dd3" width="550" height="493">

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

面试官:Java8 JVM内存结构变了,<span><span><span><i 面试官:Java8 JVM内存结构变了,<span><span><span><i style=永久代到元空间" src="http://p9.pstatp.com/large/pgc-image/cb6e05f23adc4929b5f280c47a2f9038" _fcksavedurl="http://p9.pstatp.com/large/pgc-image/cb6e05f23adc4929b5f280c47a2f9038" _fcksavedurl="http://p9.pstatp.com/large/pgc-image/cb6e05f23adc4929b5f280c47a2f9038" width="550" height="346">

再重复一遍就是对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)。

面试官:Java8 JVM内存结构变了,<span><span><span><i 面试官:Java8 JVM内存结构变了,<span><span><span><i style=永久代到元空间" src="http://p3.pstatp.com/large/pgc-image/6fbb4b07dd584053af2858c68fb5c8de" _fcksavedurl="http://p3.pstatp.com/large/pgc-image/6fbb4b07dd584053af2858c68fb5c8de" _fcksavedurl="http://p3.pstatp.com/large/pgc-image/6fbb4b07dd584053af2858c68fb5c8de" width="550" height="488">

元空间存在于本地内存,意味着只要本地内存足够,它不会出现像永久代中“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%,但是这点性能损失换来了更大的安全保障。

【编辑推荐】

  1. Tomcat 和 JVM 的性能调优经验总结!拿走不谢
  2. Jvm内部缓存选型?一篇文章为你解答疑惑
  3. 对JVM还有什么不懂的?带你深入浅出JVM!
  4. 一文带你深入理解JVM
  5. 你真的了解JVM吗?
【责任编辑:武晓燕 TEL:(010)68476606】
点赞 0

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读