写在前面
本文隶属于专栏《100个问题搞定Java虚拟机》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!
本专栏目录结构和文献引用请见100个问题搞定Java虚拟机
解答
方法区是 Java 虚拟机规范中的一个逻辑概念,常量池是方法区的一部分,而永久代和元空间则是方法区的具体实现。
JDK版本 | 逻辑概念 | HotSpot虚拟机的具体实现 | 说明 |
---|---|---|---|
JDK1.2~JDK6 | 方法区 | 永久代 | |
JDK7 | 方法区 | 永久代+部分堆 | 字符串常量池+静态变量存放在 Java 堆中 |
JDK8+ | 方法区 | 元空间+部分堆 | 字符串常量池+静态变量存放在 Java 堆中 |
补充
方法区
方法区是 JVM 内存中逻辑上划分出来的一个专门用来存放 Java 静态数据的区域,包括已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等。
永久代
永久代是 JDK7 以前 HotSpot 虚拟机对于方法区的具体实现。
之所以叫作永久代,是和分代收集算法中的新生代,老年代对应的,代表的一个"永久"不会回收的内存区域。
实际上静态资源虽然变动少,但是不回收也可能导致OOM。
在Sun公司的BUG列表中,曾出现过的若干个严重的BUG就是由于低版本的Hotspot虚拟机对此区域未完全回收而导致内存泄漏。
常量池
常量池包括全局常量池,class常量池和运行时常量池。
- 全局常量池在每个VM中只有一份,存放的是字符串常量的引用值。
- class常量池是在编译的时候每个class都有的,在编译阶段,存放的是常量的符号引用。
- 运行时常量池是在类加载完成之后,将每个class常量池中的符号引用值转存到运行时常量池中,也就是说,每个class都有一个运行时常量池,类在解析之后,将符号引用替换成直接引用,与全局常量池中的引用值保持一致。
元空间
元空间和永久代类似,都是对JVM虚拟机规范中方法区的实现。
不过元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。