You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

理解动态多态字节码:Java字节码新手的Dispatch类解析请求

Hey there! Let's break this down step by step since you're new to Java bytecode. First, let's start with what the Dispatch.java source code must look like (we can reverse-engineer it directly from the bytecode you shared), then we'll walk through each line of the bytecode to connect the dots.

Inferred Dispatch.java Source Code

This is the code that would compile to the bytecode you provided:

class A {
    public void run() {
        // The actual implementation doesn't affect our bytecode analysis
    }
}

class B extends A {
    // B inherits run() from A, or could override it—either way, dynamic dispatch handles it
}

public class Dispatch {
    // Implicit default constructor (compiler adds this since we don't define one)
    public Dispatch() {
        super();
    }

    public static void main(String[] args) {
        B b = new B();
        b.run();
    }
}

Let's Analyze the Dispatch Class Bytecode

First, let's look at the constructor for the Dispatch class:

Compiled from "Dispatch.java"
class Dispatch {
Dispatch();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return

Here's what each line does:

  • aload_0: Pushes the this reference (stored in local variable 0) onto the operand stack. Every non-static method automatically gets this as its first local variable.
  • invokespecial #1: Calls the superclass (Object) constructor. All Java constructors must call their parent's constructor first (either explicitly or implicitly), and invokespecial is used for direct, non-virtual calls to constructors or private methods. The #1 points to an entry in the class's constant pool that references Object's no-arg constructor.
  • return: Exits the constructor and returns control to the caller.

Now the main() Method Bytecode (The Interesting Part!)

This is where the dynamic dispatch happens—let's break down each line:

public static void main(java.lang.String[]);
Code:
0: new #2 // class B
3: dup
4: invokespecial #3 // Method B."":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method A.run:()V
12: return

Line-by-line breakdown:

  • new #2: Creates a new, uninitialized instance of class B. This pushes a reference to the uninitialized object onto the operand stack. The #2 is a constant pool entry pointing to the B class.
  • dup: Duplicates the top value on the operand stack (the uninitialized B reference). We need two copies because the constructor call will consume one, and we need the other to store in a local variable.
  • invokespecial #3: Calls B's no-arg constructor to initialize the object. This consumes one copy of the B reference from the stack, leaving the initialized reference ready to store.
  • astore_1: Stores the fully initialized B reference into local variable 1 (local variable 0 is the args parameter passed to main).
  • aload_1: Pushes the B reference from local variable 1 back onto the operand stack so we can call a method on it.
  • invokevirtual #4: This is the magic of dynamic dispatch! Even though the bytecode says Method A.run:()V, the JVM will look at the runtime type of the object (which is B, not A) and call the appropriate run() method. If B overrides run(), that's the one that executes; if not, it falls back to A's implementation. This is how Java achieves polymorphism.
  • return: Exits the main method and returns control to the JVM.

Key Takeaway

The invokevirtual instruction is what makes Java's polymorphism work. It doesn't just call the method defined in the declared type (A here)—it resolves the method based on the actual object type at runtime. That's why this example is called Dispatch!

内容的提问来源于stack exchange,提问作者ecdhe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:51:43