On Jan 28, 2016, at 8:06 AM, Eric Lippert <[email protected]> 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 } */
