在JDK1.8以及之后的版本中JVM的运行时数据区的结构发生了变化

其中最大的变化就是关于方法区的,比如去除了永久代,换上了元空间,并且元空间不再与堆连续,而是使用的本地内存,并把StringTable 串儿池移入了堆内,等等。

说到方法区,很多人一直搞不清楚,方法区、永久代以及元空间,这几个东西它们之间到底有什么关系?

今天就用通俗易懂的大白话来讲一讲

1、搞清楚 方法区、永久代以及元空间之间的关系

首先,我们看一下JVM运行时数据区的结构图

从上图可以看出,JVM的规范中,是把整个运行时数据区,分为了:堆、栈、方法区、程序计数器和本地方法栈。

接下来,我们先来理解两个概念:规范和实现

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

我们通常使用的JDK都是由Sun JDK和OpenJDK所提供,这也是应用最广泛的版本。

而该版本使用的JVM就是HotSpot VM。通常情况下,我们所讲的Java虚拟机指的就是HotSpot虚拟机。

了解了规范和实现的概念后,接下来,我们继续讨论 方法区

那方法区、永久代以及元空间,这几个东西它们之间到底有什么关系?

其实很简单!

方法区就是JVM里的规范,意思就是JVM规范里要求那些JVM的厂商们在实现JVM时必须有方法区这个东西,它就是个规范,规定。就相当于Java代码里的接口。

那是规范(接口)的话,就肯定要有具体的实现

那方法区的具体实现是什么呢?

简单来说,在HotSpot 虚拟机中 JDK1.6以及之前,方法区的具体实现是 永久代 PermGen

在JDK1.8以及之后,方法区的具体实现是 MateSpace元空间。

1.6和1.8都说完了,那1.7呢?

其实在1.7的时候就已经慢慢的开始去永久代化了,1.7中永久代中存储的部分数据已经开始转移到Java Heap 堆或Native Memory 本地内存中了。
比如,符号引用(Symbols)转移到了Native Memory;字符串常量池(StringTable)转移到了Java Heap;类的静态变量(class statics)转移到了Java Heap。只是在1.7的时候永久代这个概念还在,没完全去除,然后在1.8的时候,完全去除了永久代。

好,到这里,我想我已经讲清楚了。方法区、永久代以及元空间的关系就这么简单

2、堆和方法区的物理存储

为了更细化的讲解,我们将第一张图进行进一步的优化调整,调整后,如下图

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

3、永久代(PermGen)

对于习惯了在HotSpot虚拟机上开发、部署的程序员来说,很多都愿意将方法区称作永久代。

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

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

再重复一遍,就是对JDK1.7及以前版本的Hotspot中方法区的具体实现是永久代。

同时,永久代和堆逻辑上是相互隔离的,但它们使用的物理内存是连续的。

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

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

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

4、元空间(MateSpace)

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

在JDK1.8中,元空间(Metaspace)登上舞台,方法区的具体实现换成了元空间(Metaspace)。

同时,元空间不再与堆连续,而且是存在于本地内存(Native memory)

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

针对JDK1.8的调整,我们再次对内存结构图进行调整

元空间存在于本地内存,意味着只要本地内存足够,它不会出现像永久代中“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释放空间导致的垃圾收集。

5、永久代为什么被替换

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

1、为永久代设置空间大小很难确定。
一个应用动态加载的类的多少是很难确定的,如果永久代设置的过小,会频繁触发FullGC,并且可能会出现OOM。
而元空间的大小只收本地内存限制,这样出现OOM的机会比较小。

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

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

2、对永久代进行调优十分困难。
调优是为了减少FullGC,如果永久代频繁触发FullGC,会使永久代调优变得困难

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

6、StringTable为什么要放到堆

因为永久代的回收频率比较低,只在FullGC的时候才会被回收,FullGC只会在老年代或者永久代空间不足时才会触发。如果有大量的字符串被创建,放在永久代,由于永久代的回收频率低,会导致很多无用的字符串得不到及时的回收,而导致永久代空间不足。如果放到堆里,能够及时回收内存。

大白话讲清楚JVM里的方法区、永久代以及元空间相关推荐

  1. JVM(5)_方法区和大厂面试题

    文章目录 1. 堆.栈.方法区的交互关系 2. 方法区的理解 3.设置方法区大小与OOM 3.1 方法区大小 3.2 方法区OOM 4.方法区的内部结构 4.1 方法区中存储的信息 4.2 运行时常量 ...

  2. JDK1.8 JVM元数据区取代了永久代,元数据空间并不在虚拟机中,而是使用本地内存

    JDK1.8 JVM运行时内存数据区域划分.1.8同1.7比,最大的差别就是:元数据区取代了永久代.元空间的本质和永久代类似,都是对JVM规范中方法区的实现.不过元空间与永久代之间最大的区别在于:元数 ...

  3. JVM运行时数据区域——为什么jdk8用元空间替换了永久代

    以局部窥全局,这个问题其实很复杂,要弄清楚这个问题,首先要对JVM运行时数据区域划分以及各个数据区域的作用了和指掌. JVM运行时数据区域总览 JVM在执行Java程序的过程中(简称运行时)会把它所管 ...

  4. JVM堆 栈 方法区详解

    一.栈 每当启用一个线程时,JVM就为他分配一个JAVA栈,栈是以帧为单位保存当前线程的运行状态 栈是由栈帧组成,每当线程调用一个java方法时,JVM就会在该线程对应的栈中压入一个帧 只有在调用一个 ...

  5. JVM—堆栈 堆 方法区 静态区 final static 内存分配

    原文作者:一夜丶鱼龙舞 原文地址:JAVA 堆栈 堆 方法区 静态区 final static 内存分配 详解(转) 一.栈(stack)和堆(heap) (1)内存分配的策略 按照编译原理的观点,程 ...

  6. 下午花一小时整理的JVM运行时方法区

    转载于:https://blog.51cto.com/8745668/2391688

  7. JVM之 方法区、永久代(PermGen space)、元空间(Metaspace)三者的区别

    文章目录 0.前言(JVM 运行时区域) 1.PermGen(永久代) 2.Metaspace(元空间) 3.JDK6 .JDK7.JDK8 内存溢出的示例 4.元空间与本地内存 5.总结 0.前言( ...

  8. JVM之方法区、永久代(PermGen space)、元空间(Metaspace)三者的区别

    JVM体系结构 根据 JVM 规范,JVM 运行时区域大致分为 方法区.堆.虚拟机栈.本地方法栈.程序计数器 五个部分. 1).方法区 方法区是JVM 所有线程共享. 主要用于存储类的信息.常量池.方 ...

  9. java方法区超详细汇总,方法区到底是干什么用的?不懂方法区不能说了解jvm!

    目录 一.运行时数据区结构图 二.栈.堆.方法区的交互关系 三.方法区的理解 官方文档 方法区在哪里 方法区的基本理解 HotSpot中方法区的演进 四.设置方法区大小与OOM 设置方法区内存的大小 ...

  10. 36.JVM内存分哪几个区,每个区的作用是什么、如和判断一个对象是否存活、java垃圾回收机制、垃圾收集的方法有哪些、java类加载过程、类加载机制、双亲委派、Minor GC和Major GC

    36.JVM内存分哪几个区,每个区的作用是什么? 37.如和判断一个对象是否存活?(或者GC对象的判定方法) 38.简述java垃圾回收机制? 39.java中垃圾收集的方法有哪些? 40.java类 ...

最新文章

  1. 大咖分享会 | 百度首次揭秘如何构建用户画像与移动统计
  2. html请求接口_python接口自动化测试 - 2.Django开发接口
  3. Servlet容器中web.xml配置context-param与init-param
  4. mysql linux root密码忘记了怎么办_linux下忘记mysql root密码解决办法
  5. Java的接口及实例(转)
  6. bzoj 1671: [Usaco2005 Dec]Knights of Ni 骑士(BFS)
  7. [渝粤教育] 西南科技大学 机床电气控制技术 在线考试复习资料
  8. 关于UIAlertAction如何修改sheet上的字体颜色
  9. 软件开发流程知识概括
  10. 董明珠这一年:格力造芯与银隆困局
  11. 某数5代Cookies生成算法分析
  12. 今年AI论文8大领域突破:特斯拉自动驾驶入选,视频博主最利好,跨界输出很潮流...
  13. 扔鸡蛋问题-方程-动态规划
  14. hpm1005能扫描不能打印_laserjet m1005 mfp 在win10 64位机上不能打印,能扫描
  15. mstsc解决远程桌面连接提示远程终端连接数超过了允许连接数
  16. 虚假谣言,新闻的检测与分析论文
  17. 北大青鸟java第二次月考笔试_北大青鸟ACCP 4.0一期笔试模拟题二(后24题)...
  18. v16_G120调试电机优化编程
  19. 今年行情这么差,到底如何进大厂?
  20. java 获取home路径_关于JAVA_HOME等引用路径

热门文章

  1. 如何注册电子邮箱账号,教你创建email邮箱账号
  2. Win10 删除 微软输入法
  3. 《时代三部曲》感悟四
  4. 孕马血清促性腺激素PMSG的来源及主要功能
  5. [嵌入式学习]arm开发板通过NFS(网络文件系统)快捷访问和操作Ubuntu文件系统
  6. 今生梦一场,思念你的殇
  7. zeros什么意思_zeros:zeros还是zeroes?4)是什么意思?
  8. 同程内网流传的分布式凤凰缓存系统手册,竟遭GitHub强行开源下载
  9. 【听】天才在左,疯子在右,天才与疯子一线之间
  10. 从0到1CTFer成长之路环境搭建详细教程