Java code to bytecode to constant pool hashes
From Java Code → Bytecode → Constant Pool Hashes
Code Example 🎯
Let’s take the simplest code:
Java Code
public class Demo {
public static void main(String[] args) {
Demo d = new Demo();
String msg = d.sayHello();
System.out.println(msg);
}
public String sayHello() {
return "Hello World";
}
}
Step 1️⃣
Bytecode Generated 🔥
public static void main(java.lang.String[]);
0: new #2 // Create Object Demo
3: dup // Duplicate Reference
4: invokespecial #1 // Call Constructor
7: astore_1 // Store Reference in Local Variable
8: aload_1 // Load Reference
9: invokevirtual #3 // Call sayHello()
12: astore_2 // Store Result in Variable
13: getstatic #4 // Get System.out
16: aload_2 // Load Result
17: invokevirtual #5 // Call println()
20: return
Step 2️⃣
What JVM Sees 🔥
Let’s break this down:
Bytecode | Meaning | Hash |
---|---|---|
new #2 | Create Object | #2 = Demo Class |
dup | Duplicate Reference | – |
invokespecial #1 | Call Constructor | #1 = Demo.<init>() |
astore_1 | Store Reference in Local Variable | – |
aload_1 | Load Reference | – |
invokevirtual #3 | Call Method | #3 = Demo.sayHello() |
astore_2 | Store Result | – |
getstatic #4 | Get System.out | #4 = System.out |
aload_2 | Load Result | – |
invokevirtual #5 | Call println() | #5 = PrintStream.println() |
return | Method End | – |
Step 3️⃣
What are These Hashes?
These hashes represent Constant Pool Table 💪
Constant Pool Table
Hash | Type | What it Points To |
---|---|---|
#1 | Methodref | Demo.<init>()V (Constructor) |
#2 | Class | Demo Class |
#3 | Methodref | Demo.sayHello()Ljava/lang/String; |
#4 | Fieldref | System.out |
#5 | Methodref | PrintStream.println(Ljava/lang/String;)V |
Now Let’s Connect Everything 🔥
Line 1
javaCopyEditDemo d = new Demo();
Bytecode:
0: new #2 // Create Object Demo
3: dup // Duplicate Reference
4: invokespecial #1 // Call Constructor
7: astore_1 // Store Reference
✅ What Happens:
Opcode | Hash | Meaning |
---|---|---|
new #2 | #2 | Create Object Demo |
invokespecial #1 | #1 | Call Constructor Demo.<init>() |
astore_1 | – | Store Reference in Local Variable |
Line 2
String msg = d.sayHello();
Bytecode:
asmCopyEdit8: aload_1 // Load Reference
Line 2️⃣
javaCopyEditString msg = d.sayHello();
Bytecode:
8: aload_1 // Load reference 'd'
9: invokevirtual #3 // Call sayHello()
12: astore_2 // Store result in variable 'msg'
What happens here?
Opcode | Hash | Meaning |
---|---|---|
aload_1 | – | Load reference d |
invokevirtual #3 | #3 | Call method sayHello() from the object |
astore_2 | – | Store the result in msg |
How JVM Resolves this?
👉 invokevirtual #3
checks the Constant Pool Table
Constant Pool Entry for #3
#3 = Methodref Demo.sayHello()Ljava/lang/String;
✅ This means:
- Class =
Demo
- Method =
sayHello()
- Return Type =
String
Line 3️⃣
javaCopyEditSystem.out.println(msg);
Bytecode:
13: getstatic #4 // Get System.out
16: aload_2 // Load result (msg)
17: invokevirtual #5 // Call println()
20: return
What happens here?
Opcode | Hash | Meaning |
---|---|---|
getstatic #4 | #4 | Get System.out |
aload_2 | – | Load msg |
invokevirtual #5 | #5 | Call println() method |
Constant Pool Entry for #4
#4 = Fieldref java/lang/System.out Ljava/io/PrintStream;
✅ This means:
- Class =
System
- Field =
out
- Type =
PrintStream
Constant Pool Entry for #5
#5 = Methodref java/io/PrintStream.println(Ljava/lang/String;)V
✅ This means:
- Class =
PrintStream
- Method =
println
- Argument =
String
- Return =
void
Now Bhai 🧠💪
Let’s connect ALL HASHES 🔥🔥
Bytecode | Hash | Constant Pool Entry |
---|---|---|
new #2 | #2 | Class -> Demo |
invokespecial #1 | #1 | Method -> Demo.<init>() |
invokevirtual #3 | #3 | Method -> Demo.sayHello() |
getstatic #4 | #4 | Field -> System.out |
invokevirtual #5 | #5 | Method -> PrintStream.println() |
💥 Final Picture
Demo d = new Demo(); → new #2 → invokespecial #1
String msg = d.sayHello(); → invokevirtual #3
System.out.println(msg); → getstatic #4 → invokevirtual #5
Now Coming to Your Million Dollar Question 💰💪
🔥 Why This Constant Pool Exists?
✅ Because in JVM, bytecode must be small and compact
Instead of storing names like "sayHello"
or "println"
everywhere,
it stores just the HASH Reference Numbers.