jdk1.6,1.7,1.8版本方法区具体实现变化、为什么jdk1.8移除了永久代

jdk1.6,1.7,1.8版本方法区具体实现变化、为什么jdk1.8移除了永久代

  • 方法区各版本实现
  • jdk1.6
  • jdk1.7
  • jdk1.8
  • 为什么jdk1.8移除了永久代?

方法区是一个 线程共享模型,是堆的一部分,有个别名,叫做“非堆”,目的是为了跟我们真正的Java堆区分开来。非堆之所以叫非堆,是因为它是堆逻辑的一部分,仅仅只是逻辑,方法区实际的落地是分为两块。有一部分是在JVM的堆内存当中进行一个实现,包括字符串常量池,静态变量,包括类信息是放在直接内存中的。方法区在内存不足的情况下,会抛出OOM。
注意:Java官网对于方法区的规范和方法区的具体实现并不一样,因为这仅仅只是一个规范,是一个概念(存放方法的信息),而真正的实现会随着jdk的版本而进行优化,实现是会改名的,每个版本叫法可能并不一样。

方法区各版本实现

  • jdk6: 方法区在jdk6中的实现是叫做永久代
  • jdk7: 方法区在jdk7中的实现中叫做永久代(去部分永久代),也叫做Perm Space,jdk7中做了一部分去永久代的操作,Perm Space使用的是JVM自己的内存(是JVM自己的内存,由JVM从系统中抢占过来的内存)
  • jdk8: 方法区在jdk8中的实现是叫做元空间,也叫做元数据区,也叫做叫做Meta Space,Meta Space使用的直存(直接内存,也就是我们系统的可用内存)加粗样式

jdk1.6

jdk1.7以前的hotspot里面的结构有:堆、栈、永久代、程序计数器。此时的方法区,hotspot的实现是永久代。
永久代存放的内容有:

  • 类信息
  • 字段
  • 方法
  • 静态变量和全局变量
  • 运行时常量池(里面包含字符串常量池)
  • Class引用
  • ClassLoader的引用
  • 方法表

这里看出永久代分配内存空间的方式是预先操作。

jdk1.7

jdk1.7将永久代中的静态变量和运行时常量池中的字符串常量池转移到了堆中,也就是说全局变量和其他常量(非字符串常量)还遗留在永久代中。

jdk1.7及之前,会为每个类加载器分配一个内存列表,它会进行线性分配,整个内存块的大小,取决于类加载器的类型,比如代理和反射对应的类加载器的内存块会小一些,而之前的版本在卸载类的时候,会对这些内存列表进行单独卸载。永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。

jdk1.8

jdk1.8移除了永久代,用元空间代替,将 HotSpot 与 JRockit 合二为一。

GC的时候在发现某个类加载器已经具备了回收条件之后,会将整个类加载器以及它相关的整个空间进行卸载,这样可以减少内存碎片,节省GC的扫描以及压缩的时间。

在原来永久代的东西都被搬到了元空间,所以相对于1.7版本我们并不需要记多少东西,还依然是字符串常量池和静态变量装到了堆中,其余的装到元空间。

每个Java对象的对象头里,_klass字段会指向一个VM内部用来记录类的元数据用的InstanceKlass对象;InsanceKlass里有个_java_mirror字段,指向该类所对应的Java镜像——java.lang.Class实例。

HotSpot VM会给Class对象注入一个隐藏字段“klass”,用于指回到其对应的InstanceKlass对象。这样,klass与mirror之间就有双向引用,可以来回导航。
这个模型里,java.lang.Class实例并不负责记录真正的类元数据,而只是对VM内部的InstanceKlass对象的一个包装供Java的反射访问用。

在JDK 6及之前的HotSpot VM里,静态字段依附在InstanceKlass对象的末尾;而在JDK 7开始的HotSpot VM里,静态字段依附在java.lang.Class对象的末尾。

为什么jdk1.8移除了永久代?

jdk1.7方法区实现是Perm Space,使用的是JVM自己的内存(是JVM从系统抢占过来的内存),
jdk1.8方法区实现是Meta Space,也就是元空间,使用的直存(直接内存,也就是我们系统的可用内存)。

因为类的总数、常量池的大小、以及方法的数量是不能够预估出来的,所以说没有办法很好的设置一个Perm Space的空间大小,而Meta Space的优势就在于,元空间分配的是直接内存,也就是我们系统的可用内存,所以说一旦本地的内存都会内存溢出,也就证明这个jar包根本不适合放在这个机器上。

用户也可以为元空间设置一个最大值,但是最好不要设置,因为它会根据元数据的大小动态的去调整空间的容量。

你可能感兴趣的:(jvm,jvm,jdk,方法区,元空间)