JVM类加载与反射:从Class文件到运行时类的全景——Klass模型、类加载器、Metaspace与反射的桥接机制
反射凭什么认识你的类 某开发者写过这样一段代码,当时觉得平平无奇: Method method = obj.getClass().getDeclaredMethod("secretLogic", String.class); method.setAccessible(true); Object result = method.invoke(obj, "hacked!"); 运行完才反应过来——凭什么?一个 Class 对象拿在手里,连 private 方法都能翻出来调用,连参数签名都一清二楚。JVM 到底在背后存了什么东西,让反射可以"看见"一个类的全部内脏? 答案就在 HotSpot 的 Klass 模型 里。 📌 前置知识:本文假设读者知道 .class 文件是 javac 编译产物、JVM 基本内存分区(堆、栈、方法区)的常识。如果不清楚方法区和 Metaspace 的关系,后文有图。 全景先览:JVM 中的类在哪 在深入 Klass 之前,先看一张全局地图——一个类从 .class 文件到进入 JVM 运行时,到底经过了哪些区域。 这张图先有一个印象就行——关键记住一点:一个类被加载后,JVM 在 Metaspace 里存了一份"类模板"(InstanceKlass),在 Heap 里放了一个轻量的"Java 镜像"(Class 对象)。 反射读的元信息来自前者,你代码里 getClass() 拿到的是后者。 类模板:HotSpot 眼中的"类" 你写的每一个 Java 类,在 HotSpot 内部都有一个对应的 C++ 对象来描述它——这就是 Klass 模型。 Klass 继承链 Klass ← 所有类的抽象基类 ├── InstanceKlass ← 普通 Java 类(你写的 99% 的类) │ ├── InstanceMirrorKlass ← Class 对象本身(镜子) │ └── InstanceRefKlass ← 引用类型(软/弱/虚引用) ├── ArrayKlass ← 数组类 │ ├── TypeArrayKlass ← 基本类型数组(int[]) │ └── ObjArrayKlass ← 对象数组(String[]) ⚠️ 新手提示:Klass 不是 Class。Klass 是 C++ 层面的数据结构,存在 Metaspace; java.lang.Class 是 Java 层面的对象,存在 Heap。日常说"类模板"通常指 InstanceKlass。 ...