Bytecode carving game - how to declare local variables inside a call to super() ?

Tagir Valeev amaembo at gmail.com
Thu Apr 23 14:53:00 UTC 2020


Wow, Java puzzlers!

I bet it's

super(switch(0) {default->{
... the rest is simple...}})

чт, 23 апр. 2020 г., 19:39 Remi Forax <forax at univ-mlv.fr>:

> I'm sure you want to play a game,
> what about i give you the bytecode, show me the corresponding Java code :)
>
> Let say i have this code:
> public interface Fun {
>   record Point(int x, int y) { }
>   record Circle(Point center, int radius) { }
>
>   class Shape {
>     private final double distanceToOrigin;
>
>     public Shape(double distanceToOrigin) {
>       this.distanceToOrigin = distanceToOrigin;
>     }
>   }
>
>   class Disc extends Shape {
>     public Disc(Circle circle) {
>       super(Math.sqrt(circle.center.x * circle.center.x + circle.center.y
> * circle.center.y));
>     }
>   }
> }
>
> The code in super() has a lot of repetition, circle.center is used 4 times
> !
>
> The generated bytecode for this example (it is the same using javac or
> ecj, the eclipse compiler),
> shows 4 calls to getfield Fun$Circle.center:LFun$Point;
>
> $ javap -c Fun\$Disc.class
> Compiled from "Fun.java"
> public class Fun$Disc extends Fun$Shape {
>   public Fun$Disc(Fun$Circle);
>     Code:
>        0: aload_0
>        1: aload_1
>        2: getfield      #8                  // Field
> Fun$Circle.center:LFun$Point;
>        5: getfield      #14                 // Field Fun$Point.x:I
>        8: aload_1
>        9: getfield      #8                  // Field
> Fun$Circle.center:LFun$Point;
>       12: getfield      #14                 // Field Fun$Point.x:I
>       15: imul
>       16: aload_1
>       17: getfield      #8                  // Field
> Fun$Circle.center:LFun$Point;
>       20: getfield      #20                 // Field Fun$Point.y:I
>       23: aload_1
>       24: getfield      #8                  // Field
> Fun$Circle.center:LFun$Point;
>       27: getfield      #20                 // Field Fun$Point.y:I
>       30: imul
>       31: iadd
>       32: i2d
>       33: invokestatic  #23                 // Method
> java/lang/Math.sqrt:(D)D
>       36: invokespecial #29                 // Method
> Fun$Shape."<init>":(D)V
>       39: return
> }
>
>
> Now, refactoring the java source code using the jdk 14, I was able to get
> ecj to generate this bytecode:
>
> $ javap -c Fun\$Disc.class
> Compiled from "Fun.java"
> public class Fun$Disc extends Fun$Shape {
>   public Fun$Disc(Fun$Circle);
>     Code:
>        0: aload_0
>        1: aload_1
>        2: getfield      #8                  // Field
> Fun$Circle.center:LFun$Point;
>        5: astore_2
>        6: aload_2
>        7: getfield      #14                 // Field Fun$Point.x:I
>       10: istore_3
>       11: aload_2
>       12: getfield      #20                 // Field Fun$Point.y:I
>       15: istore        4
>       17: iload_3
>       18: iload_3
>       19: imul
>       20: iload         4
>       22: iload         4
>       24: imul
>       25: iadd
>       26: i2d
>       27: invokestatic  #23                 // Method
> java/lang/Math.sqrt:(D)D
>       30: invokespecial #29                 // Method
> Fun$Shape."<init>":(D)V
>       33: return
> }
>
> as you can see i'm able to declare local variables, the slot 2, 3 and 4,
> to store center, center.x and center.y, inside the call to super !
>
> How to do declare a local variable inside a call to super (several
> solutions) ?
> What is the Java code corresponding to the bytecode above ?
>
> regards,
> Rémi
>


More information about the amber-dev mailing list