Why doesn’t the JVM compile everything (all methods in all classes) to machine code up front?
JIT compilation takes time
- JIT compilation is expensive — analyzing and optimizing methods takes CPU cycles.
- Compiling everything upfront would cause longer startup time and higher resource use.
JVM goal: Fast startup + optimize only when needed.
Most code is cold
Studies (including JVM benchmarks) show that 90%+ of methods are cold in many real-world applications.
Compiling everything would bloat code cache and impact performance (especially on memory-constrained devices).
If only half the methods become hot, then only those hot methods are JIT-compiled into machine code and stored in the code cache.
But what does “loaded in memory” really mean?
Class loading (via the ClassLoader):
- When a class is loaded, the entire bytecode of the class is read into memory (usually into Metaspace).
- This includes:
- All method bytecode
- Field info
- Constant pool
- Annotations, metadata, etc.
So yes, the whole class bytecode is loaded into memory — even if only some methods are used.
JIT Compilation (runtime, method-based):
- The JVM only JIT-compiles individual hot methods, not the whole class.
- These hot methods are translated to machine code and stored in the code cache.
- Cold methods remain in memory as bytecode, and are interpreted when/if called.
Important clarification:
The entire class (metadata + bytecode) is always loaded into memory after
Class.forName()
or any reference.
But:
Only selected hot methods are converted to machine code and loaded into the JVM code cache.
Think of it like this:
Example Class:
javaCopyEditpublic class BigClass {
public void methodA() { ... } // called 1M times → HOT
public void methodB() { ... } // never called → COLD
public void methodC() { ... } // called 2 times → COLD
}
What’s in memory:
Component | In memory? | Where stored |
---|---|---|
Bytecode (A, B, C) | JVM Metaspace | |
Machine code for methodA() | Code Cache | |
Machine code for methodB() | Not compiled | |
Machine code for methodC() | Not compiled |