JDK 6 之前的 HotSpot VM,静态变量保存在类的元数据 InstanceKlass
的末尾
JDK 7 之后的 HotSpot VM,静态变量则是保存在类的 Java 镜像 java.lang.Class
实例的末尾
在 HotSpot VM 中,Java 对象 Java object
、类的元数据 InstanceKlass
、类的 Java 镜像 Java mirror
三者的关系如下
Java object InstanceKlass Java mirror
[ _mark ] (java.lang.Class instance)
[ _klass ] --> [ ... ] <-\
[ fields ] [ _java_mirror ] --+> [ _mark ]
[ ... ] | [ _klass ]
| [ fields ]
\ [ klass ]
假如有下面这段代码
class A {
static int value = 1;
}
在 JDK 6 前,是这样的:
Java object InstanceKlass Java mirror
[ _mark ] (java.lang.Class instance)
[ _klass ] --> [ ... ] <-\
[ fields ] [ _java_mirror ] --+> [ _mark ]
[ ... ] | [ _klass ]
[ A.value ] | [ fields ]
\ [ klass ]
在 JDK 7 后,则是这样的:
Java object InstanceKlass Java mirror
[ _mark ] (java.lang.Class instance)
[ _klass ] --> [ ... ] <-\
[ fields ] [ _java_mirror ] --+> [ _mark ]
[ ... ] | [ _klass ]
| [ fields ]
\ [ klass ]
[ A.value ]
那么,InstanceKlass
和 java.lang.Class
实例都是放在哪里呢?
对于
InstanceKlass
JDK 7 前的 HotSpot VM 里,它是存放在 GC 堆中所谓的永久代
Permanent Generation
(简称PermGen)中JDK 8 后的 HotSpot VM 则完全移除了永久代,它改为存放在本地内存
Native Memory
中的元空间Metaspace
中(方法区的一种实现方式)
对于
java.lang.Class
实例对象- 它从来都只是普通的 Java 对象,一样存放在 GC 堆里
上面的分析比较绕,总结一下静态变量在 JVM 内存区域的位置:
JDK 6
堆中的永久代(方法区)
此时方法区(用永久代来实现)被视作堆的一个逻辑部分
JDK 7
堆(Class 对象)
废除永久代,方法区用元空间实现,静态变量跟随 Class 对象移到堆中
JDK 8 ~ 至今
堆(Class 对象)
另外,关于 JVM 内存区域中 堆、方法区、永久代
之间的关系,需要结合《深入理解 Java 虚拟机》帮助理解
- Post link: http://example.com/2022/02/09/Java%E9%9D%99%E6%80%81%E5%8F%98%E9%87%8F-static-%E5%AD%98%E5%82%A8%E4%BD%8D%E7%BD%AE%E7%9A%84%E6%8E%A2%E8%AE%A8/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.