Nestmates

John Rose john.r.rose at oracle.com
Thu Jan 28 18:48:21 UTC 2016


On Jan 28, 2016, at 8:06 AM, Eric Lippert <ericlippert at gmail.com> wrote:
> 
> Later versions generated a private bridge method in Bravo that called Alpha.Echo and then had the generated closure invoke that helper method.

FTR here's the a version of Eric's example, coded with lambdas and then with inner classes.
Some disassembly is included.

In both cases javac emits a non-public helper method in Bravo that is shared with the Delta object.
In the case of lambdas, it fits together securely with a method handle.
In the case of inner classes, there is a package-scope "hole" in the access control.

The IC case would be fixed by nestmate access, if we figure out how to expand "protected"
access across a nest.  Which is tricky.  It might be that protected access must always go
through delegation via private methods with "proprietary" rights to call protected.

— John

http://cr.openjdk.java.net/~jrose/draft/ClosureCallSuper.java <http://cr.openjdk.java.net/~jrose/draft/ClosureCallSuper.java>

class ClosureCallSuper {
    public static void main(String... av) {
        new Bravo().charlie();
        new Bravo_with_IC().charlie();
    }
}

interface Delta { void invoke(); }
class Alpha {
    public void echo() { System.out.println("Alpha.echo"); }
}
class Bravo extends Alpha {
    public @Override void echo() { System.out.println("Bravo.echo"); }
    public void charlie() {
        int x = 123;
        Delta foxtrot = () ->
        {
            this.echo(); //Bravo.echo
            super.echo(); //Alpha.echo
            System.out.println(x); //123
        };
        foxtrot.invoke();
    }
}
class Bravo_with_IC extends Alpha {
    public @Override void echo() { System.out.println("Bravo_with_IC.echo"); }
    public void charlie() {
        int x = 123;
        Delta foxtrot = new Delta() {
        public void invoke() {
            Bravo_with_IC.this.echo(); //Bravo_with_IC.echo
            Bravo_with_IC.super.echo(); //Alpha.echo
            System.out.println(x); //123
        } };
        foxtrot.invoke();
    }
}

/*
$ javac ClosureCallSuper.java && java ClosureCallSuper
Bravo.echo
Alpha.echo
123
Bravo_with_IC.echo
Alpha.echo
123

$ javap -p -c Bravo.class
Compiled from "ClosureCallSuper.java"
class Bravo extends Alpha {
  Bravo();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method Alpha."<init>":()V
       4: return

  public void echo();
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String Bravo.echo
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return

  public void charlie();
    Code:
       0: bipush        123
       2: istore_1
       3: aload_0
       4: iload_1
       5: invokedynamic #5,  0              // InvokeDynamic #0:invoke:(LBravo;I)LDelta;
[[ (javap includes this info in -v mode)
BootstrapMethods:
  0: #29 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
    Method arguments:
      #30 ()V
      #31 invokespecial Bravo.lambda$charlie$0:(I)V
      #30 ()V
]]
      10: astore_2
      11: aload_2
      12: invokeinterface #6,  1            // InterfaceMethod Delta.invoke:()V
      17: return

  private void lambda$charlie$0(int);
    Code:
       0: aload_0
       1: invokevirtual #7                  // Method echo:()V
       4: aload_0
       5: invokespecial #8                  // Method Alpha.echo:()V
       8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      11: iload_1
      12: invokevirtual #9                  // Method java/io/PrintStream.println:(I)V
      15: return
}

$ javap -p -c Bravo_with_IC.class
Compiled from "ClosureCallSuper.java"
class Bravo_with_IC extends Alpha {
  Bravo_with_IC();
    Code:
       0: aload_0
       1: invokespecial #2                  // Method Alpha."<init>":()V
       4: return

  public void echo();
    Code:
       0: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #4                  // String Bravo_with_IC.echo
       5: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return

  public void charlie();
    Code:
       0: bipush        123
       2: istore_1
       3: new           #6                  // class Bravo_with_IC$1
       6: dup
       7: aload_0
       8: iload_1
       9: invokespecial #7                  // Method Bravo_with_IC$1."<init>":(LBravo_with_IC;I)V
      12: astore_2
      13: aload_2
      14: invokeinterface #8,  1            // InterfaceMethod Delta.invoke:()V
      19: return

  static void access$001(Bravo_with_IC);  <<<< THIS SHOULD BE PRIVATE BUT IS PACKAGE
    Code:
       0: aload_0
       1: invokespecial #1                  // Method Alpha.echo:()V
       4: return
}

*/

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/attachments/20160128/56c7807c/attachment-0001.html>


More information about the valhalla-spec-experts mailing list