方法区与 Java 堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
方法区也被称为永久代。
方法区和永久代的关系
《Java 虚拟机规范》只是规定了有方法区这么个概念和它的作用,并没有规定如何去实现它。那么,在不同的 JVM 上方法区的实现肯定是不同的了。方法区和永久代的关系很像 Java 中接口和类的关系,类实现了接口,而永久代就是 HotSpot 虚拟机对虚拟机规范中方法区的一种实现方式。也就是说,永久代是 HotSpot 的概念,方法区是 Java 虚拟机规范中的定义,是一种规范,而永久代是一种实现,一个是标准一个是实现,其他的虚拟机实现并没有永久代这一说法。
为什么要将永久代 (PermGen) 替换为元空间 (MetaSpace) 呢?
- 整个永久代有一个 JVM 本身设置固定大小上限,无法进行调整,而元空间使用的是直接内存,受本机可用内存的限制,虽然元空间仍旧可能溢出,但是比原来出现的几率会更小。
当你元空间溢出时会得到如下错误:java.lang.OutOfMemoryError: MetaSpace
你可以使用-XX:MaxMetaspaceSize标志设置最大元空间大小,默认值为 unlimited,这意味着它只受系统内存的限制。-XX:MetaspaceSize调整标志定义元空间的初始大小如果未指定此标志,则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。
- 元空间里面存放的是类的元数据,这样加载多少类的元数据就不由MaxPermSize控制了, 而由系统的实际可用空间来控制,这样能加载的类就更多了。
静态变量存放在哪个区域?
HotSpot VM,JDK 6 及之前版本静态变量存放在永久代(Permanent Generation,使用永久代实现的方法区)中;JDK 7 开始,静态变量改存放到 java.lang.Class 对象的末尾,即 Heap 中。