字节码分析-内部类
源码
package java.bytecode;
/**
* 内部类示例 - 演示成员内部类、静态内部类
*/
public class InnerClassExample {
private int outerField = 100;
private static int staticOuterField = 200;
// 成员内部类
public class InnerClass {
private int innerField;
public InnerClass(int innerField) {
this.innerField = innerField;
}
public void innerMethod() {
System.out.println("InnerClass.innerMethod(): " + innerField);
System.out.println("Access outer field: " + outerField);
}
}
// 静态内部类
public static class StaticInnerClass {
private static int staticInnerField = 300;
public static void staticInnerMethod() {
System.out.println("StaticInnerClass.staticInnerMethod()");
System.out.println("Static outer field: " + staticOuterField);
}
public void instanceMethod() {
System.out.println("StaticInnerClass.instanceMethod()");
}
}
public void createInnerClass() {
InnerClass inner = new InnerClass(50);
inner.innerMethod();
}
}
结构化反解析
Classfile /D:/zcp/github/yggdrasil/java/bytecode/InnerClassExample.class
...
{
private int outerField;
descriptor: I
flags: ACC_PRIVATE
private static int staticOuterField;
descriptor: I
flags: ACC_PRIVATE, ACC_STATIC
public void createInnerClass();
Code:
0: new #16 // class java/bytecode/InnerClassExample$InnerClass
3: dup
4: aload_0
5: bipush 50
7: invokespecial #18 // Method java/bytecode/InnerClassExample$InnerClass."<init>":(Ljava/bytecode/InnerClassExample;I)V
10: astore_1
11: aload_1
12: invokevirtual #21 // Method java/bytecode/InnerClassExample$InnerClass.innerMethod:()V
15: return
static int access$000(java.bytecode.InnerClassExample);
descriptor: (Ljava/bytecode/InnerClassExample;)I
flags: ACC_STATIC, ACC_SYNTHETIC
Code:
0: aload_0
1: getfield #7 // Field outerField:I
4: ireturn
static int access$100();
descriptor: ()I
flags: ACC_STATIC, ACC_SYNTHETIC
Code:
0: getstatic #1 // Field staticOuterField:I
3: ireturn
}
InnerClasses:
public #35= #16 of #2; //InnerClass=class java/bytecode/InnerClassExample$InnerClass of class java/bytecode/InnerClassExample
public static #38= #36 of #2; //StaticInnerClass=class java/bytecode/InnerClassExample$StaticInnerClass of class java/bytecode/InnerClassExample
详细说明
内部类命名
内部类在字节码中通过$分隔符命名:
InnerClassExample$InnerClass- 成员内部类InnerClassExample$StaticInnerClass- 静态内部类
成员内部类
成员内部类持有外部类的引用,构造方法需要外部类实例:
public void createInnerClass();
Code:
0: new #16 // class InnerClassExample$InnerClass
3: dup
4: aload_0 // 加载外部类实例(this)
5: bipush 50
7: invokespecial #18 // Method InnerClass$InnerClass."<init>":(InnerClassExample;I)V
合成方法(Synthetic Methods)
编译器会生成access$000等合成方法,用于内部类访问外部类的私有成员:
static int access$000(InnerClassExample);
flags: ACC_STATIC, ACC_SYNTHETIC
Code:
0: aload_0
1: getfield #7 // Field outerField:I
4: ireturn
ACC_SYNTHETIC标志表示这是编译器生成的方法- 用于访问外部类的私有字段和方法
InnerClasses属性
InnerClasses属性记录内部类信息:
InnerClasses:
public #35= #16 of #2; //InnerClass=class InnerClassExample$InnerClass
public static #38= #36 of #2; //StaticInnerClass=class InnerClassExample$StaticInnerClass
静态内部类
静态内部类不持有外部类实例引用,可以独立创建:
public static class StaticInnerClass {
// 可以访问外部类的静态成员
// 不能访问外部类的实例成员
}
访问外部类成员
- 成员内部类:通过合成方法访问外部类私有成员
- 静态内部类:只能访问外部类的静态成员
使用场景
- 成员内部类:需要访问外部类实例成员时使用
- 静态内部类:不需要访问外部类实例时使用,性能更好