JIT(Just-In-Time,即时编译)编译后的代码(即本地机器码)主要存储在 Java 虚拟机(JVM)的 Code Cache(代码缓存区) 中。
以下是更详细的解释:
- Code Cache(代码缓存区):
- 这是 JVM 堆外内存(Off-Heap Memory)的一个专门区域。
- 当 JVM 的 JIT 编译器(如 HotSpot VM 中的 C1 或 C2 编译器)将热点 Java 字节码(
.class
文件中的字节码)编译成本地机器指令(Native Code)后,这些生成的机器码就会被存放在 Code Cache 中。 - Code Cache 是 JVM 内存管理的一部分,其大小可以通过 JVM 参数(如
-XX:ReservedCodeCacheSize
和-XX:InitialCodeCacheSize
)进行配置。 - 这个区域是可执行的,CPU 可以直接从这里读取并执行编译好的机器指令,从而获得接近原生程序的性能。
- 为什么需要 Code Cache?
- 性能提升:解释执行字节码比直接执行本地机器码要慢得多。JIT 编译将频繁执行的“热点代码”编译成本地机器码并缓存起来,后续执行时可以直接运行这些高效的机器码,极大地提升了程序的运行速度。
- 动态优化:JIT 编译器可以在运行时收集程序的执行信息(如方法调用频率、分支走向等),并基于这些信息进行激进的、特定于当前运行环境的优化(如内联、逃逸分析优化等),这是 AOT(Ahead-Of-Time)编译在编译时难以做到的。编译和优化后的结果就存放在 Code Cache 里。
- 按需编译:并非所有字节码都会被 JIT 编译。只有被识别为“热点”的代码才会被编译并放入 Code Cache,这节省了编译时间和内存空间。
- 与堆内存的区别:
- 堆内存(Heap):主要用于存储 Java 程序在运行时创建的对象实例。由垃圾收集器(GC)管理。
- Code Cache:专门用于存储 JIT 编译生成的可执行机器码。它不属于 Java 堆,通常由 JVM 自身管理其生命周期和内存回收(当编译后的代码不再需要时,JVM 会从 Code Cache 中清除它)。
总结: JIT 编译后的本地机器码被存储在 JVM 内部一个名为 Code Cache 的、位于堆外的特殊内存区域中。CPU 直接执行这个区域里的代码,从而实现了 Java 程序的高性能运行。
THE END