謎のaccess$0メソッドの話。

謎のメソッドがコンパイラによって生成されているのだけど、
何故そのメソッドが作られるのか、どの様な役割を持っているのか、
全く持って意味が分からないので、誰か教えてクダサシ。


解決しるました。


まず、こんなコードを書くます。

public class Deny {
  public void execute() {
    dddd();
  }
  public void dddd() {
    for (Method m : getClass().getDeclaredMethods()) {
      System.out.println(m.toString());
    }
    System.setProperty("bbb", getClass().getName());
    String s = System.getProperty("bbb");
    System.out.println(s);
    new Throwable().printStackTrace(System.out);
  }
}
public class Ok extends Deny {
  @Override
  public void execute() {
    AccessController.doPrivileged(new PrivilegedAction<Object>() {
      @Override
      public Object run() {
        Ok.super.execute();
        return null;
      }
    });
  }
  public void execute2() {
    AccessController.doPrivileged(new PrivilegedAction<Object>() {
      @Override
      public Object run() {
        new Hoge().hoge(Ok.this);
        return null;
      }
    });
  }
}
public class Hoge {
  public void hoge(final Ok ok) {
    AccessController.doPrivileged(new PrivilegedAction<Object>() {
      @Override
      public Object run() {
        ok.dddd();
        return null;
      }
    });
  }
}

Ok.classに、ソースコード上では存在しない、access$0と言う謎メソッドが生成されているます。
そやつだけ抜粋すると、こんな感じ。

static void access$0(aa.bb.cc.Ok);
  Code:
   0:  aload_0
   1:  invokespecial  #31; //Method aa/bb/cc/Deny.execute:()V
   4:  return

何というか、ほぼ全く何もしていないstaticメソッドでつ。
何故、コイツが必要になるのか良く分かりません。
僕が知りたいのは、以下の通り。

  • どの様な目的で、この謎メソッドがコンパイラによって作成されるのか?
  • どの様な条件で、この謎メソッドがコンパイラによって作成されるのか?
  • この謎メソッドの実装に関する仕様書はどこにあるのか?

知っている方がいたらぜひ教えてクダサシ。
何となくだけど、今分かっているのは、

-java.security.AccessController

  • java.security.PrivilegedAction

この辺が関係があるっぽい…?のかな…と言う事だけでつ。
不思議。


インナークラスとsuperと言うキーワードがセットになると、出来るっぽい感じ。


全部をjavapしてみたのは、以下。
ちなみに、eclipseのJDTがコンパイルした.classファイルをjavapしているます。

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

public void execute();
  Code:
   0:  aload_0
   1:  invokevirtual  #15; //Method dddd:()V
   4:  return

public void dddd();
  Code:
   0:  aload_0
   1:  invokevirtual  #18; //Method java/lang/Object.getClass:()Ljava/lang/Class;
   4:  invokevirtual  #22; //Method java/lang/Class.getDeclaredMethods:()[Ljava/lang/reflect/Method;
   7:  dup
   8:  astore  4
   10:  arraylength
   11:  istore_3
   12:  iconst_0
   13:  istore_2
   14:  goto  35
   17:  aload  4
   19:  iload_2
   20:  aaload
   21:  astore_1
   22:  getstatic  #28; //Field java/lang/System.out:Ljava/io/PrintStream;
   25:  aload_1
   26:  invokevirtual  #34; //Method java/lang/reflect/Method.toString:()Ljava/lang/String;
   29:  invokevirtual  #40; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   32:  iinc  2, 1
   35:  iload_2
   36:  iload_3
   37:  if_icmplt  17
   40:  ldc  #46; //String bbb
   42:  aload_0
   43:  invokevirtual  #18; //Method java/lang/Object.getClass:()Ljava/lang/Class;
   46:  invokevirtual  #48; //Method java/lang/Class.getName:()Ljava/lang/String;
   49:  invokestatic  #51; //Method java/lang/System.setProperty:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
   52:  pop
   53:  ldc  #46; //String bbb
   55:  invokestatic  #55; //Method java/lang/System.getProperty:(Ljava/lang/String;)Ljava/lang/String;
   58:  astore_1
   59:  getstatic  #28; //Field java/lang/System.out:Ljava/io/PrintStream;
   62:  aload_1
   63:  invokevirtual  #40; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   66:  new  #59; //class java/lang/Throwable
   69:  dup
   70:  invokespecial  #61; //Method java/lang/Throwable."<init>":()V
   73:  getstatic  #28; //Field java/lang/System.out:Ljava/io/PrintStream;
   76:  invokevirtual  #62; //Method java/lang/Throwable.printStackTrace:(Ljava/io/PrintStream;)V
   79:  return

}

Compiled from "Ok.java"
public class aa.bb.cc.Ok extends aa.bb.cc.Deny{
public aa.bb.cc.Ok();
  Code:
   0:  aload_0
   1:  invokespecial  #8; //Method aa/bb/cc/Deny."<init>":()V
   4:  return

public void execute();
  Code:
   0:  new  #15; //class aa/bb/cc/Ok$1
   3:  dup
   4:  aload_0
   5:  invokespecial  #17; //Method aa/bb/cc/Ok$1."<init>":(Laa/bb/cc/Ok;)V
   8:  invokestatic  #20; //Method java/security/AccessController.doPrivileged:(Ljava/security/PrivilegedAction;)Ljava/lang/Object;
   11:  pop
   12:  return

public void execute2();
  Code:
   0:  new  #27; //class aa/bb/cc/Ok$2
   3:  dup
   4:  aload_0
   5:  invokespecial  #29; //Method aa/bb/cc/Ok$2."<init>":(Laa/bb/cc/Ok;)V
   8:  invokestatic  #20; //Method java/security/AccessController.doPrivileged:(Ljava/security/PrivilegedAction;)Ljava/lang/Object;
   11:  pop
   12:  return

static void access$0(aa.bb.cc.Ok);
  Code:
   0:  aload_0
   1:  invokespecial  #31; //Method aa/bb/cc/Deny.execute:()V
   4:  return

}

Compiled from "Ok.java"
class aa.bb.cc.Ok$1 extends java.lang.Object implements java.security.PrivilegedAction{
final aa.bb.cc.Ok this$0;

aa.bb.cc.Ok$1(aa.bb.cc.Ok);
  Code:
   0:  aload_0
   1:  aload_1
   2:  putfield  #12; //Field this$0:Laa/bb/cc/Ok;
   5:  aload_0
   6:  invokespecial  #14; //Method java/lang/Object."<init>":()V
   9:  return

public java.lang.Object run();
  Code:
   0:  aload_0
   1:  getfield  #12; //Field this$0:Laa/bb/cc/Ok;
   4:  invokestatic  #23; //Method aa/bb/cc/Ok.access$0:(Laa/bb/cc/Ok;)V
   7:  aconst_null
   8:  areturn

}

Compiled from "Ok.java"
class aa.bb.cc.Ok$2 extends java.lang.Object implements java.security.PrivilegedAction{
final aa.bb.cc.Ok this$0;

aa.bb.cc.Ok$2(aa.bb.cc.Ok);
  Code:
   0:  aload_0
   1:  aload_1
   2:  putfield  #12; //Field this$0:Laa/bb/cc/Ok;
   5:  aload_0
   6:  invokespecial  #14; //Method java/lang/Object."<init>":()V
   9:  return

public java.lang.Object run();
  Code:
   0:  new  #23; //class aa/bb/cc/Hoge
   3:  dup
   4:  invokespecial  #25; //Method aa/bb/cc/Hoge."<init>":()V
   7:  aload_0
   8:  getfield  #12; //Field this$0:Laa/bb/cc/Ok;
   11:  invokevirtual  #26; //Method aa/bb/cc/Hoge.hoge:(Laa/bb/cc/Ok;)V
   14:  aconst_null
   15:  areturn

}

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

public void hoge(aa.bb.cc.Ok);
  Code:
   0:  new  #16; //class aa/bb/cc/Hoge$1
   3:  dup
   4:  aload_0
   5:  aload_1
   6:  invokespecial  #18; //Method aa/bb/cc/Hoge$1."<init>":(Laa/bb/cc/Hoge;Laa/bb/cc/Ok;)V
   9:  invokestatic  #21; //Method java/security/AccessController.doPrivileged:(Ljava/security/PrivilegedAction;)Ljava/lang/Object;
   12:  pop
   13:  return

}

Compiled from "Hoge.java"
class aa.bb.cc.Hoge$1 extends java.lang.Object implements java.security.PrivilegedAction{
final aa.bb.cc.Hoge this$0;

aa.bb.cc.Hoge$1(aa.bb.cc.Hoge, aa.bb.cc.Ok);
  Code:
   0:  aload_0
   1:  aload_1
   2:  putfield  #14; //Field this$0:Laa/bb/cc/Hoge;
   5:  aload_0
   6:  aload_2
   7:  putfield  #16; //Field val$ok:Laa/bb/cc/Ok;
   10:  aload_0
   11:  invokespecial  #18; //Method java/lang/Object."<init>":()V
   14:  return

public java.lang.Object run();
  Code:
   0:  aload_0
   1:  getfield  #16; //Field val$ok:Laa/bb/cc/Ok;
   4:  invokevirtual  #27; //Method aa/bb/cc/Ok.dddd:()V
   7:  aconst_null
   8:  areturn

}

JDK1.6に付属しているjavacでコンパイルすると、微妙に違いがあったりします。
こんな感じ。

Compiled from "Ok.java"
public class aa.bb.cc.Ok extends aa.bb.cc.Deny{
public aa.bb.cc.Ok();
  Code:
   0:  aload_0
   1:  invokespecial  #2; //Method aa/bb/cc/Deny."<init>":()V
   4:  return

public void execute();
  Code:
   0:  new  #3; //class aa/bb/cc/Ok$1
   3:  dup
   4:  aload_0
   5:  invokespecial  #4; //Method aa/bb/cc/Ok$1."<init>":(Laa/bb/cc/Ok;)V
   8:  invokestatic  #5; //Method java/security/AccessController.doPrivileged:(Ljava/security/PrivilegedAction;)Ljava/lang/Object;
   11:  pop
   12:  return

public void execute2();
  Code:
   0:  new  #6; //class aa/bb/cc/Ok$2
   3:  dup
   4:  aload_0
   5:  invokespecial  #7; //Method aa/bb/cc/Ok$2."<init>":(Laa/bb/cc/Ok;)V
   8:  invokestatic  #5; //Method java/security/AccessController.doPrivileged:(Ljava/security/PrivilegedAction;)Ljava/lang/Object;
   11:  pop
   12:  return

static void access$001(aa.bb.cc.Ok);
  Code:
   0:  aload_0
   1:  invokespecial  #1; //Method aa/bb/cc/Deny.execute:()V
   4:  return

}

微妙にaccess$の後の数字の採番ルールが違いまつね。