5

Just tried JDK17 on Eclipse 2021-09 to have it fail with a java.lang.VerifyError, which wasn't very helpful itself. I tracked it down to a switch statement, that gets fed a value pulled out of a Map or another generic type. If I use a local variable in the switch statement instead, everything works as intended.

Test code:

import java.util.HashMap;
import java.util.Map;

public class SwitchFail {
  public static void main(String[] args) {
    //doesnt work
    Map<Integer, String> stringMap = new HashMap<>();
    stringMap.put(1, "Test");
    switch(stringMap.get(1)) {
    }

    //works
    String plainString = "Test";
     switch(plainString) {
    }
  }
}

This throws the following error:

Error: Unable to initialize main class SwitchFail
Caused by: java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    SwitchFail.main([Ljava/lang/String;)V @33: invokevirtual
  Reason:
    Type 'java/lang/Object' (current frame, stack[0]) is not assignable to 'java/lang/String'
  Current Frame:
    bci: @33
    flags: { }
    locals: { '[Ljava/lang/String;', 'java/util/HashMap', 'java/lang/Object' }
    stack: { 'java/lang/Object' }
  Bytecode:
    0000000: bb00 1059 b700 124c 2b04 b800 1312 19b9
    0000010: 001b 0300 572b 04b8 0013 b900 2102 0059
    0000020: 4db6 0025 57b1  

                   
            

Didn't try another JDK between 11 and 17 yet. Switches gained some new functions between those versions, so that might be it. Maybe it's a problem in the Eclipse JDT or my local JDK, so any tries to reproduce this error on another configuration or IDE would be great. Tried on OpenJDK (build 17+35-2724) for macOS.

Edit: Also happens on

List<String> stringList = Arrays.asList("Test");
switch(stringList.get(0)) {}

Most likely an issue with the new JDT for Java 17 or my local installation.

Zhedar
  • 3,480
  • 1
  • 21
  • 44
  • How about the case where you get the string from the map, assign it to a temporary variable. and switch on the temporary? – user16632363 Sep 15 '21 at 17:05
  • 2
    Using Eclipse Version: 2020-09 (4.17.0) Build id: 20200910-1200 your code works. –  RichardFeynman Sep 15 '21 at 17:05
  • @RichardFeynman - I am inclined to suspect a compiler problem, and I think your experience might support that. – user16632363 Sep 15 '21 at 17:06
  • @user16632363 Saving it to a local var first works. This looks like some type of type inference issue. Trying on a windows machine or the Oracle JDK next. – Zhedar Sep 15 '21 at 17:09
  • What's the question? – erickson Sep 15 '21 at 17:09
  • I'm going to go so far as to say what I think the compiler bug is: ecj is failing to insert the implicit cast that results from calling `get` with a map of a generic type because it doesn't look into the switch body to realize that the narrowed type is required. – chrylis -cautiouslyoptimistic- Sep 15 '21 at 17:23
  • @chrylis-cautiouslyoptimistic- Yes, it has to do with generic type inference as it also happens with `List stringList = Arrays.asList("Test"); switch(stringList.get(0)) {}`. It's probably rooted in the JDT or my local installation. – Zhedar Sep 15 '21 at 17:26
  • Eclipse 2021-09 does not support Java 17. You have installed the preview of Java 17 support that will be released in December. Please report this issue to Eclipse here: https://bugs.eclipse.org/bugs/enter_bug.cgi?product=JDT – howlger Sep 15 '21 at 18:32
  • @howlger Just filed a bug there. Thanks for the hint. I wanted to get some feedback first. – Zhedar Sep 15 '21 at 18:45

2 Answers2

3

It is a problem with your Eclipse, not with Java-17 itself. Java-17 has been released only yesterday. Wait for some time until the IDEs are updated to support Java-17.

Demo:

import java.util.HashMap;
import java.util.Map;

public class SwitchFail {
    public static void main(String[] args) {
        Map<Integer, String> stringMap = new HashMap<>();
        stringMap.put(1, "Test");
        switch (stringMap.get(1)) {
        default:
            System.out.println("Hello");
        }

        String plainString = "Test";
        switch (plainString) {
        default:
            System.out.println("Hi");
        }
    }
}

A sample run:

[~/Desktop]: java SwitchFail.java
Hello
Hi

Test with jar:

[~/Desktop/java17]: javac SwitchFail.java 
[~/Desktop/java17]: jar -cvf java17test.jar .
added manifest
adding: SwitchFail.java(in = 379) (out= 212)(deflated 44%)
adding: SwitchFail.class(in = 920) (out= 546)(deflated 40%)
adding: .DS_Store(in = 6148) (out= 178)(deflated 97%)
[~/Desktop/java17]: java -cp java17test.jar SwitchFail
Hello
Hi

The JDK on my system:

[~/Desktop/java17]: java -version
openjdk version "17" 2021-09-14
OpenJDK Runtime Environment (build 17+35-2724)
OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)
Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • Also getting the same result when executing that via `java -jar` directly. Although still compiled and exported to jar via eclipse. – Zhedar Sep 15 '21 at 17:12
  • @Zhedar - That's what I have mentioned that it's a problem with your Eclipse, not with Java-17 itself. Create jar without using Eclipse. – Arvind Kumar Avinash Sep 15 '21 at 17:13
  • @Zhedar - I have added an update for jar as well. Feel free to comment in case of any doubt or issue. – Arvind Kumar Avinash Sep 15 '21 at 17:18
  • 2
    Thank you for your help and feedback. When I compile the class using javac, everything works as intended. I guess it's a bug in the JDT or my local installation is broken. – Zhedar Sep 15 '21 at 17:28
  • @Zhedar The worst thing you can do is _"Wait for some time"_ instead of making sure it has been reported to Eclipse. Please note, you have probably installed the current preview of Java 17 support that will be released on December 15, 2021. – howlger Sep 15 '21 at 18:46
  • 2
    @howlger You've already seen this, but this bug is reported under https://bugs.eclipse.org/bugs/show_bug.cgi?id=576008 – Zhedar Sep 15 '21 at 19:02
3

This was indeed a bug in Eclipse's JDT. I can confirm this was fixed after Bug 576093 was closed. There is an update available.

Zhedar
  • 3,480
  • 1
  • 21
  • 44