字节码分析-继承

源码

package java.bytecode;

import java.bytecode.BaseClass;

/**
 * 继承示例 - 演示继承、方法重写、super调用
 */
public class InheritanceExample extends BaseClass {

    private String childField = "Child";

    public InheritanceExample() {
        super();
    }

    public InheritanceExample(String message) {
        super(message);
    }

    // 重写父类方法
    @Override
    public void baseMethod() {
        super.baseMethod();
        System.out.println("InheritanceExample.baseMethod()");
    }

    // 调用父类protected方法
    public void callProtectedMethod() {
        protectedMethod();
    }

    public String getChildField() {
        return childField;
    }
}

结构化反解析

Classfile /D:/zcp/github/yggdrasil/java/bytecode/InheritanceExample.class
  Last modified 2025-12-3; size 805 bytes
  MD5 checksum 97b91542392420a8091f376b3d10aca0
  Compiled from "InheritanceExample.java"
public class java.bytecode.InheritanceExample extends java.bytecode.BaseClass
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #2.#3          // java/bytecode/BaseClass."<init>":()V
   #2 = Class              #4             // java/bytecode/BaseClass
   #3 = NameAndType        #5.#6          // "<init>":()V
   #4 = Utf8               java/bytecode/BaseClass
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = String             #8             // Child
   #8 = Utf8               Child
   #9 = Fieldref           #10.#11        // java/bytecode/InheritanceExample.childField:Ljava/lang/String;
  #10 = Class              #12            // java/bytecode/InheritanceExample
  #11 = NameAndType        #13:#14        // childField:Ljava/lang/String;
  #12 = Utf8               java/bytecode/InheritanceExample
  #13 = Utf8               childField
  #14 = Utf8               Ljava/lang/String;
  #15 = Methodref          #2.#16         // java/bytecode/BaseClass."<init>":(Ljava/lang/String;)V
  #16 = NameAndType        #5:#17         // "<init>":(Ljava/lang/String;)V
  #17 = Utf8               (Ljava/lang/String;)V
  #18 = Methodref          #2.#19         // java/bytecode/BaseClass.baseMethod:()V
  #19 = NameAndType        #20:#6         // baseMethod:()V
  #20 = Utf8               baseMethod
  #21 = Fieldref           #22.#23        // java/lang/System.out:Ljava/io/PrintStream;
  #22 = Class              #24            // java/lang/System
  #23 = NameAndType        #25:#26        // out:Ljava/io/PrintStream;
  #24 = Utf8               java/lang/System
  #25 = Utf8               out
  #26 = Utf8               Ljava/io/PrintStream;
  #27 = String             #28            // InheritanceExample.baseMethod()
  #28 = Utf8               InheritanceExample.baseMethod()
  #29 = Methodref          #30.#31        // java/io/PrintStream.println:(Ljava/lang/String;)V
  #30 = Class              #32            // java/io/PrintStream
  #31 = NameAndType        #33:#17        // println:(Ljava/lang/String;)V
  #32 = Utf8               java/io/PrintStream
  #33 = Utf8               println
  #34 = Methodref          #10.#35        // java/bytecode/InheritanceExample.protectedMethod:()V
  #35 = NameAndType        #36:#6         // protectedMethod:()V
  #36 = Utf8               protectedMethod
  #37 = Utf8               Code
  #38 = Utf8               LineNumberTable
  #39 = Utf8               callProtectedMethod
  #40 = Utf8               getChildField
  #41 = Utf8               ()Ljava/lang/String;
  #42 = Utf8               SourceFile
  #43 = Utf8               InheritanceExample.java
{
  private java.lang.String childField;
    descriptor: Ljava/lang/String;
    flags: ACC_PRIVATE

  public java.bytecode.InheritanceExample();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/bytecode/BaseClass."<init>":()V
         4: aload_0
         5: ldc           #7                  // String Child
         7: putfield      #9                  // Field childField:Ljava/lang/String;
        10: return
      LineNumberTable:
        line 13: 0
        line 10: 4
        line 14: 10

  public java.bytecode.InheritanceExample(java.lang.String);
    descriptor: (Ljava/lang/String;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=2, args_size=2
         0: aload_0
         1: aload_1
         2: invokespecial #15                 // Method java/bytecode/BaseClass."<init>":(Ljava/lang/String;)V
         5: aload_0
         6: ldc           #7                  // String Child
         8: putfield      #9                  // Field childField:Ljava/lang/String;
        11: return
      LineNumberTable:
        line 17: 0
        line 10: 5
        line 18: 11

  public void baseMethod();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #18                 // Method java/bytecode/BaseClass.baseMethod:()V
         4: getstatic     #21                 // Field java/lang/System.out:Ljava/io/PrintStream;
         7: ldc           #27                 // String InheritanceExample.baseMethod()
         9: invokevirtual #29                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        12: return
      LineNumberTable:
        line 23: 0
        line 24: 4
        line 25: 12

  public void callProtectedMethod();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokevirtual #34                 // Method protectedMethod:()V
         4: return
      LineNumberTable:
        line 29: 0
        line 30: 4

  public java.lang.String getChildField();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: getfield      #9                  // Field childField:Ljava/lang/String;
         4: areturn
      LineNumberTable:
        line 33: 0
}
SourceFile: "InheritanceExample.java"

详细说明

继承关系

在字节码中,继承关系通过类的定义和父类索引表示:

public class java.bytecode.InheritanceExample extends java.bytecode.BaseClass

super调用

使用invokespecial指令调用父类方法,这是super关键字在字节码中的实现:

public InheritanceExample();
  Code:
     0: aload_0
     1: invokespecial #1  // Method java/bytecode/BaseClass."<init>":()V

invokespecial用于:
- 调用父类构造方法(super())
- 调用父类方法(super.baseMethod())
- 调用私有方法

方法重写

子类重写父类方法时,使用invokevirtual调用子类方法,实现多态:

public void baseMethod();
  Code:
     0: aload_0
     1: invokespecial #18  // Method java/bytecode/BaseClass.baseMethod:()V
     4: getstatic     #21  // Field java/lang/System.out:Ljava/io/PrintStream;
     7: ldc           #27  // String InheritanceExample.baseMethod()
     9: invokevirtual #29  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    12: return

protected方法调用

子类调用父类的protected方法时,使用invokevirtual指令:

public void callProtectedMethod();
  Code:
     0: aload_0
     1: invokevirtual #34  // Method protectedMethod:()V
     4: return

方法调用指令的区别

虚方法表(vtable)

JVM使用虚方法表实现多态。当调用invokevirtual时,JVM会根据对象的实际类型查找虚方法表,找到正确的方法实现。