5

Is the below a bug in Java 20 or, am I missing something? If you compile/run the below program, you get the expected printouts. But, if you uncomment the single line in the switch:

import static java.lang.System.*;
public class Main {
    record Point(int x, int y, Color color){}
    enum Color {RED, BLUE, YELLOW}
    public static void main(String[] args) {
        testSwitch(new Point(10,20,Color.BLUE));
        testSwitch(new Point(10,20,Color.RED));
        testSwitch("vbjhjbhbjhbj");
        testSwitch(1.012);
        testSwitch(Color.YELLOW);
    }
    static void testSwitch(Object o){
        switch(o){
            case null -> out.println("Null");
            case Color c -> out.println("Color: "+c);
            //case Point(var x, var y, Color c) when c == Color.RED -> out.printf("Red point x=%d, y=%d\n",x,y);
            case Point(var x, var y, var color) -> out.printf("Point x=%d, y=%d, color=%s\n",x,y,color);
            case String s when s.length() >=7 -> out.printf("Big string: '%s', of size %d\n",s,s.length());
            case String s -> out.printf("Small string: %s, of size %d\n",s,s.length());
            default -> out.println("Unexpected value: " + o);
        }
    }
}

the code compiles fine, but at runtime I get (on MacOS 13.3.1 ARM64 JDK 20 with preview features enabled) this run-time failure:

/Library/Java/JavaVirtualMachines/jdk-20.jdk/Contents/Home/bin/java --enable-preview -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=50788:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath /Users/hristo/projects/java20tests/java20tests/out/production/java20tests Main
Error: Unable to initialize main class Main
Caused by: java.lang.VerifyError: Bad local variable type
Exception Details:
  Location:
    Main.testSwitch(Ljava/lang/Object;)V @309: aload
  Reason:
    Type top (current frame, locals[7]) is not assignable to reference type
  Current Frame:
    bci: @309
    flags: { }
    locals: { 'java/lang/Object', 'java/lang/Object', integer, top, 'Main$Point', integer, integer, top, integer, integer, integer, integer, 'Main$Color', integer }
    stack: { 'java/io/PrintStream', 'java/lang/String', '[Ljava/lang/Object;', '[Ljava/lang/Object;', integer }
  Bytecode:
    0000000: 2a4c 033d 2b1c ba00 2800 00aa 0000 019a
    0000010: ffff ffff 0000 0003 0000 0021 0000 002c
    0000020: 0000 0043 0000 013f 0000 0174 b200 2c12
    0000030: 32b6 0034 a701 832b c000 0a4e b200 2c2d
    0000040: b800 3aba 003f 0000 b600 34a7 016c 2bc0
    0000050: 0007 3a04 1904 b600 4336 0803 3609 1508
    0000060: b800 4715 09ba 004c 0000 ab00 0000 00db
    0000070: 0000 0002 ffff ffff 0000 00db 0000 0000
    0000080: 0000 001a 1508 3605 1904 b600 4d36 0a03
    0000090: 360b 150a b800 4715 0bba 004c 0000 ab00
    00000a0: 0000 00a1 0000 0002 ffff ffff 0000 00a1
    00000b0: 0000 0000 0000 001a 150a 3606 1904 b600
    00000c0: 503a 0c03 360d 190c 150d ba00 5400 00ab
    00000d0: 0000 004b 0000 0002 ffff ffff 0000 004b
    00000e0: 0000 0000 0000 0019 190c 3a07 1907 b200
    00000f0: 18a5 0009 0436 0da7 ffcf b200 2c12 5805
    0000100: bd00 0259 0315 05b8 0047 5359 0415 06b8
    0000110: 0047 53b6 005a 57a7 00a0 b200 2c12 5e06
    0000120: bd00 0259 0315 05b8 0047 5359 0415 06b8
    0000130: 0047 5359 0519 0753 b600 5a57 a700 7b04
    0000140: 3609 a7ff 1c05 3da7 febd 2bc0 003b 3a08
    0000150: 1908 b600 6010 07a2 0008 063d a7fe a8b2
    0000160: 002c 1263 05bd 0002 5903 1908 5359 0419
    0000170: 08b6 0060 b800 4753 b600 5a57 a700 3b2b
    0000180: c000 3b3a 09b2 002c 1265 05bd 0002 5903
    0000190: 1909 5359 0419 09b6 0060 b800 4753 b600
    00001a0: 5a57 a700 15b2 002c 2ab8 003a ba00 6700
    00001b0: 00b6 0034 a700 03a7 0011 4cbb 006a 592b
    00001c0: b600 6c2b b700 70bf b1                 
  Exception Handler Table:
    bci [86, 89] => handler: 442
    bci [138, 141] => handler: 442
    bci [190, 193] => handler: 442
  Stackmap Table:
    append_frame(@4,Object[#2],Integer)
    same_frame(@44)
    same_frame(@55)
    same_frame(@78)
    full_frame(@94,{Object[#2],Object[#2],Integer,Top,Object[#7],Top,Top,Top,Integer,Integer},{})
    same_frame(@132)
    full_frame(@146,{Object[#2],Object[#2],Integer,Top,Object[#7],Integer,Top,Top,Integer,Integer,Integer,Integer},{})
    same_frame(@184)
    full_frame(@198,{Object[#2],Object[#2],Integer,Top,Object[#7],Integer,Integer,Top,Integer,Integer,Integer,Integer,Object[#10],Integer},{})
    same_frame(@232)
    full_frame(@250,{Object[#2],Object[#2],Integer,Top,Object[#7],Integer,Integer,Object[#10],Integer,Integer,Integer,Integer,Object[#10],Integer},{})
    full_frame(@282,{Object[#2],Object[#2],Integer,Top,Object[#7],Integer,Integer,Top,Integer,Integer,Integer,Integer,Object[#10],Integer},{})
    full_frame(@319,{Object[#2],Object[#2],Integer,Top,Object[#7],Integer,Top,Top,Integer,Integer,Integer,Integer},{})
    full_frame(@325,{Object[#2],Object[#2],Integer,Top,Object[#7],Top,Top,Top,Integer,Integer},{})
    full_frame(@330,{Object[#2],Object[#2],Integer},{})
    full_frame(@351,{Object[#2],Object[#2],Integer,Top,Top,Top,Top,Top,Object[#59]},{})
    full_frame(@383,{Object[#2],Object[#2],Integer},{})
    same_frame(@421)
    chop_frame(@439,2)
    same_locals_1_stack_item_frame(@442,Object[#104])
    same_frame(@456)

Process finished with exit code 1
skomisa
  • 16,436
  • 7
  • 61
  • 102
Hristo Stoyanov
  • 1,508
  • 3
  • 15
  • 24
  • I think it's a compiler bug. By any chance are you using eclipse? – Elliott Frisch Apr 09 '23 at 14:38
  • 3
    Definitely a bug. Java source code should never compile to bytecodes that give a verify error. But ... make sure you raise the bug report against the correct compiler ... – Stephen C Apr 09 '23 at 14:44
  • I test the code, in Ubuntu 20, OpenJDK Runtime Environment Temurin-20+36, Compile Command: `javac -source 20 --enable-preview Main.java`, and run command `java --enable-preview Main`, then get same error message.(java.lang.VerifyError: Bad local variable type Exception Details: Location: Main.testSwitch(Ljava/lang/Object;)V @309: aload) – life888888 Apr 09 '23 at 14:56
  • if add `-Xlint:preview`, `javac -source 20 -Xlint:preview --enable-preview Main.java`, will get more detaile warining: `Main.java:16: warning: [preview] patterns in switch statements are a preview feature and may be removed in a future release. case Point(var x, var y, Color c) when c == Color.RED -> out.printf("Red point x=%d, y=%d\n",x,y); ^ Main.java:16: warning: [preview] deconstruction patterns are a preview feature and may be removed in a future release.....` – life888888 Apr 09 '23 at 14:59
  • 1
    @life888888. I expect the warnings, since I deliberately use preview feature. But it is not OK if the thing compiles and fails at runtime. Here is the JDK printout on my MacBook Air M1 running Ventura 13.3.1 (e.g. latest), but this see like a bug in all JDK 20 distros: ``` java -version java version "20" 2023-03-21 Java(TM) SE Runtime Environment (build 20+36-2344) Java HotSpot(TM) 64-Bit Server VM (build 20+36-2344, mixed mode, sharing) ``` – Hristo Stoyanov Apr 09 '23 at 18:56
  • 1
    @Hristo Stoyanov, I also agree that this might be a problem with JDK 20.x, so I tested on my Ubuntu 20.04 + OpenJDK Runtime Environment Temurin-20+36 and got the same error message as you. (Error: Unable to initialize main class Main Caused by: java.lang.VerifyError: Bad local variable type) – life888888 Apr 10 '23 at 02:29
  • 5
    It’s clearly a bug that javac is producing a class file that doesn’t verify. There are a couple open bugs that seem related, e.g., [JDK-8302865](https://bugs.openjdk.org/browse/JDK-8302865) and [JDK-8304863](https://bugs.openjdk.org/browse/JDK-8304863). You might try this on a JDK 21 build. – Stuart Marks Apr 10 '23 at 05:15
  • 1
    Thanks @StuartMarks for confirming, I filed a bug (internal review ID : 9075078). Hopefully jdk 20 is fixed soon, so we can taste all these new features! – Hristo Stoyanov Apr 10 '23 at 07:50

1 Answers1

1

As confirmed by @stuartmarks (see comments) this is Java 20 compiler bug.

Hristo Stoyanov
  • 1,508
  • 3
  • 15
  • 24