字节码分析-继承
源码
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
方法调用指令的区别
invokespecial- 用于调用父类方法、构造方法、私有方法,不支持多态invokevirtual- 用于调用实例方法,支持多态(虚方法调用)invokestatic- 用于调用静态方法invokeinterface- 用于调用接口方法
虚方法表(vtable)
JVM使用虚方法表实现多态。当调用invokevirtual时,JVM会根据对象的实际类型查找虚方法表,找到正确的方法实现。