浅谈方法区,永久代与元空间

浅谈方法区,永久代与元空间

在我学习JVM运行时数据区的时候就有一个疑惑,永久代与元空间到底是啥?它们到底在哪?JVM规定的运行时数据区域只有五块,也没有永久代和元空间啊,对于这个问题我打算彻底搞懂他。(注:本文均是Hotspot虚拟机实现方式)

JVM载入类的时候,需要存储类的元数据(即已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据),存储这些数据的区域就叫做方法区。方法区是JVM的一个规范,而永久代和元空间是对其具体的实现,在JDK7中是永久代,在JDK8中是元空间。不过永久代和元空间并不是完全一样的,下面具体介绍一下两者。

永久代

永久代是一块连续的内存空间,它的垃圾回收是跟老年代的垃圾回收绑定的,两者只要有一个内存满了,两个区域都会进行垃圾回收。因为这个原因有的人就把他归入堆中,跟堆中的其他区域一起管理。我们可以通过-XX:PermSize-XX: MaxPermSize设置永久代的最大值,即使不设置也有默认大小,32位JVM的大小是64M,64位JVM的大小是82M。

在JDK6及以前,字符串常量池、静态变量等还是方法区的一部分,也就是在永久代中,但在JDK7的时候把这部分从方法区中移除,在堆中开启一块区域进行存放。

元空间

首先元空间与永久代最大的不同在于:元空间并不在虚拟机之中,而是使用的本地内存,这就导致了元空间的默认大小是没有限制的(但是会受到本地内存大小的限制)。我们可以通过-XX:MetaspaceSize-XX:MaxMetaspaceSize来设置元空间大小。

还有一点值得注意的,对于一个已死的类与类加载器,其回收将会在实用内存达到 MaxMetaspaceSize 的时候进行。

我们知道了永久代和元空间的基本概念,但是为什么要做这个改变呢?

  1. 类及方法的信息等比较难确定其大小,到现在都没有一个好算法能提前算出永久代/元空间需要多大的空间,因此难以指定永久代的大小,太小了容易永久代溢出,太大则容易老年代溢出。
  2. 永久代会给GC带来不必要的复杂性,并且回收效率偏低。

你可能感兴趣的:(JVM)