写在前面

本文隶属于专栏《100个问题搞定Java虚拟机》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和文献引用请见100个问题搞定Java虚拟机

解答

方法区是 Java 虚拟机规范中的一个逻辑概念,(运行时)常量池是方法区的一部分,用于存放编译期生成的各种字面量和符号引用,而永久代和元空间则是方法区的具体实现。
JDK版本逻辑概念HotSpot虚拟机的具体实现说明
JDK1.2~JDK6方法区永久代
JDK7方法区永久代+部分堆字符串常量池+静态变量存放在 Java 堆中
JDK8+方法区元空间+部分堆字符串常量池+静态变量存放在 Java 堆中

补充

方法区

方法区是 JVM 内存中逻辑上划分出来的一个专门用来存放 Java 静态数据的区域,包括已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。

永久代

永久代是 JDK7 以前 HotSpot 虚拟机对于方法区的具体实现。

之所以叫作永久代,是和分代收集算法中的新生代,老年代对应的,代表的一个"永久"不会回收的内存区域。

实际上静态资源虽然变动少,但是不回收也可能导致OOM。

在Sun公司的BUG列表中,曾出现过的若干个严重的BUG就是由于低版本的Hotspot虚拟机对此区域未完全回收而导致内存泄漏。

常量池

常量池包括全局常量池,class常量池和运行时常量池。

  1. 全局常量池在每个VM中只有一份,存放的是字符串常量的引用值。
  2. class常量池是在编译的时候每个class都有的,在编译阶段,存放的是常量的符号引用。
  3. 运行时常量池是在类加载完成之后,将每个class常量池中的符号引用值转存到运行时常量池中,也就是说,每个class都有一个运行时常量池,类在解析之后,将符号引用替换成直接引用,与全局常量池中的引用值保持一致。

元空间

元空间和永久代类似,都是对JVM虚拟机规范中方法区的实现。

不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。

Q.E.D.


大数据开发工程师,精通 Spark,擅长 Java 和 Scala