字节码分析-内部类

源码

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

详细说明

内部类命名

内部类在字节码中通过$分隔符命名:

成员内部类

成员内部类持有外部类的引用,构造方法需要外部类实例:

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

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 {
    // 可以访问外部类的静态成员
    // 不能访问外部类的实例成员
}

访问外部类成员

使用场景