方法区存储类元数据(如字段、方法、常量池、静态变量等)而非class对象本身;class对象是jvm在堆中创建的代理实例,用于访问方法区中的元数据。

方法区中存储的不是“Class对象”本身,而是类的元数据(如字段、方法、接口信息、常量池等),以及一个由JVM在类加载时创建的java.lang.Class实例——这个实例确实存于堆中,但它的存在是为了代表并访问方法区里的元数据。
Class实例在堆中,类元数据在方法区
很多人误以为Class对象就“放在方法区”,其实不然:
- JVM加载一个类时,会把类的结构信息(全限定名、父类、修饰符、字段表、方法表、常量池等)解析后存入方法区(Java 8+ 是元空间);
- 同时,JVM会在堆内存中创建一个
java.lang.Class类型的对象,它就像一个“句柄”或“代理”,提供对方法区中该类元数据的访问入口; - 这个
Class对象可被Java程序直接使用(比如String.class、obj.getClass()),但它本身是堆中的普通对象,也受GC管理——只是通常不会被回收,因为有类加载器强引用。
Class对象的生命周期与类加载过程强绑定
Class对象的创建和销毁严格对应类的加载与卸载阶段:
- 它在类初始化完成之后立即存在,即当类首次被主动使用(如new、调用静态方法、访问静态字段等),触发类加载流程(加载→验证→准备→解析→初始化)后,JVM才生成对应的
Class实例; - 只要该类的类加载器还存活,且该
Class对象仍被引用(如被静态变量持有、被其他类引用),它就不会被GC回收; - 只有当类加载器被回收(如Web应用重启时旧ClassLoader被弃用)、且该类所有实例都已不可达、且该
Class对象本身无任何强引用时,它才可能被回收——这是类卸载的前提条件之一。
方法区中存储什么?不是Class对象,而是它的“蓝图”
方法区保存的是类的静态结构描述,包括:
- 运行时常量池(含字符串字面量、符号引用等);
- 字段信息(名称、类型、修饰符);
- 方法字节码、参数、异常表;
- 类的继承关系、实现的接口列表;
- 静态变量(
static字段)——注意:它们的值存在方法区,但如果是引用类型,指向的对象仍在堆中。
换句话说,方法区存的是“类怎么长这样”,而Class对象是“这个类在Java世界里的身份证”,二者分工明确、协同工作。
常见误区澄清
几个容易混淆的点需要特别注意:
-
“String.class 是方法区里的东西” —— 错。它是堆中
Class对象的引用,通过它才能读取方法区中的String类元数据; - “Class对象能被序列化” —— 不能直接序列化,因为它包含大量JVM内部指针,且依赖运行时状态;
-
“每个new出来的对象都带一份Class信息” —— 不是。所有同类型实例共享同一个
Class对象,它只有一份,位于堆中,被所有实例间接引用(对象头中存有指向它的指针)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











