class对象与静态变量在jdk 7+中一体存放于堆内存:class对象携带所有静态字段值或引用,作为其内存布局的尾部组成部分;元空间仅存类结构信息,不存静态值。

Class 对象和 static 静态变量在 JVM 中是“一体存放、逻辑共生”的关系:静态变量不是独立存在的一块内存,而是作为 Class 对象的一部分,直接嵌入在其堆内存布局的尾部。
Class 对象本身就在堆中(JDK 7+)
从 JDK 7 开始,Class 对象不再放在方法区(永久代),而是作为普通 Java 对象分配在堆内存里。它由类加载器在加载类时创建,生命周期与该类加载器绑定。
- 每个被加载的类,对应唯一一个 Class 实例(如
String.class就是一个堆中的对象) - 这个 Class 实例不仅存元数据(字段名、方法签名等),还携带所有静态字段的实际值或引用
- 你可以用
System.out.println(Student.class)打印出类似class Student@12345678的地址,说明它确实是堆中可寻址的对象
静态变量是 Class 对象的隐式字段
编译器把每个 static 变量当作 Class 对象的“内置成员”,就像你写了一个私有字段一样,只是不显式声明。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
-
public static int COUNT = 100;→ 数值100直接存放在 Class 对象所在的堆内存区域中 -
public static Map<string object> cache = new HashMap();</string>→ 引用变量cache存在 Class 对象内部,而new HashMap()实例本身也分配在堆(可能是年轻代) - 它们在 Class 对象内存结构中紧邻排布,没有额外指针跳转,访问效率高
元空间只存描述,不存值
JDK 8+ 的元空间(Metaspace)只保存类的结构信息:常量池、字段表、方法字节码、注解等——这些是“只读模板”。真正可变的静态值,从来不在元空间里。
- OOM 报错
java.lang.OutOfMemoryError: Java heap space时,如果根因是静态集合不断扩容,说明问题就在堆里的 Class 对象及其附带的静态引用上 - 而报
java.lang.OutOfMemoryError: Metaspace,通常是因为加载了太多类(比如热部署泄漏),跟静态变量内容无关
验证方式:用工具看真实内存布局
光看文档容易混淆,动手观察最可靠:
- 用
jmap -histo <pid></pid>查看堆中是否存在你的类名对应的 Class 实例(类型显示为java.lang.Class) - 用 VisualVM 或 MAT 打开堆转储,搜索该 Class 对象,在支配树(Dominator Tree)中展开,能看到 static 字段作为其直接子节点被持有
- 修改静态变量后再次 dump,对比同一 Class 对象的字段值变化,就能确认它确实在堆中随 Class 对象一起更新
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










