Skip to content

Instantly share code, notes, and snippets.

@yoggy
Created June 18, 2015 06:23
Show Gist options
  • Save yoggy/eba30fc025e4ca889936 to your computer and use it in GitHub Desktop.
Save yoggy/eba30fc025e4ca889936 to your computer and use it in GitHub Desktop.
Javaでinner classのprivateメソッドの呼び出しにはinvokestaticが使われるのが仕様みたい?

まず、PseudoSketch.javaというファイルを用意する。

public class PseudoSketch {
    class A {
        private void a() {
            System.out.println("a");
        }
    }

    class B extends A {
        private void a() {
            System.out.println("b");
        }
    }

    public void setup() {
        B c = new B();
        A d = new B();
        c.a();
        d.a();
    }

    public static void main(String args[]) {
        PseudoSketch sketch = new PseudoSketch();
        sketch.setup();
    }
}

次に、コンパイルしてclassファイルを作る。

$ javac PseudoSketch.java
$ ls
PseudoSketch$A.class
PseudoSketch$B.class
PseudoSketch.class
PseudoSketch.java

作成されたclassファイルをjavapコマンドを使って逆アセンブルする。

$ javap -p -c PseudoSketch.class

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

  public void setup();
    Code:
       0: new           #2                  // class PseudoSketch$B
       3: dup
       4: aload_0
       5: invokespecial #3                  // Method PseudoSketch$B."<init>":(LPseudoSketch;)V
       8: astore_1
       9: new           #2                  // class PseudoSketch$B
      12: dup
      13: aload_0
      14: invokespecial #3                  // Method PseudoSketch$B."<init>":(LPseudoSketch;)V
      17: astore_2
      18: aload_1
      19: invokestatic  #4                  // Method PseudoSketch$B.access$000:(LPseudoSketch$B;)V
      22: aload_2
      23: invokestatic  #5                  // Method PseudoSketch$A.access$100:(LPseudoSketch$A;)V
      26: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #6                  // class PseudoSketch
       3: dup
       4: invokespecial #7                  // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #8                  // Method setup:()V
      12: return
}

注目するのは、main()でsketch.setup()を呼び出しているときと、 setup()内でc.a()、d.a()を呼びだしている部分の逆アセンブル結果の違い。

sketch.setup()の逆アセンブル結果

       8: aload_1
       9: invokevirtual #8                  // Method setup:()V



c.a()、d.a()の逆アセンブル結果

      18: aload_1
      19: invokestatic  #4                  // Method PseudoSketch$B.access$000:(LPseudoSketch$B;)V
      22: aload_2
      23: invokestatic  #5                  // Method PseudoSketch$A.access$100:(LPseudoSketch$A;)V
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment