Language selector

The Curious Case of JEP 443

Update

The issue has been solved, please go to the post with solution.

Note: I’m leaving the original post below in case someone bumps to a similar issue in the future. Sometimes it’s easier to search using the problem ;-)

While preparing my Deep Dive talk on Java 21 for friendly Java User Groups, I’ve noticed a curious case of JEP 443: Unnamed Patterns and Variables (Preview). I’ve managed to create a reproducer, so I’d like to share the findings here.

I assembled a simple demo of the JEP. It’s obviously very nice and for sure it will improve Java’s abilities to shine in data-first coding scenarios.

However, this JEP is not only about switch and ifs, it’s also about lambdas, catch blocks and so on. Let’s take a look at the following code to show you what I mean…

1String s = "abc";
2try {
3    int i = Integer.parseInt(s);
4    System.out.println("Parsed " + i);
5} catch (NumberFormatException _ignored) {
6    System.out.println("Bad number: " + s);
7}

As we can see, in line 5 we’re trying to clearly say that we don’t care about the actual exception we received. We only care about its type. But as we all know, even naming things seriously won’t stop others from (mis)using it (I’m looking at you, sun.misc.Unsafe fanbois!)

Therefore, we decide to play it safe and put JEP 443 into action, and write catch (NumberFormatException _). This way the compiler will ensure nobody will call _ignored.printStackTrace(); or something… And the code looks like this:

1String s = "abc";
2try {
3    int i = Integer.parseInt(s);
4    System.out.println("Parsed " + i);
5} catch (NumberFormatException _) {
6    System.out.println("Bad number: " + s);
7}

So I prepared this code, hit Run in the IDE, and… it didn’t work the way I expected. I was expecting, obviously:

1Bad number: abc

And what I got, was

1Error: LinkageError occurred while loading main class [class.name.here]
2java.lang.ClassFormatError: Illegal field name "" in class [class/name/here]

Excuse me?

curious case of a button

Lucky me, my very first IDE when I started learning Java in 2003 was notepad.exe, so I basically run:

1java --enable-preview --source 21 ./src/main/java/all/packages/of/JEP443Demo.java

… and this works as expected! I saw:

1Bad number: abc

(along with a warning about preview features, of course.)

Also in jshell it works like a charm:

jshell

So apparently it seems that JEP 443 doesn’t like to work in this case with… Maven and Gradle. I still don’t know what’s the actual cause and what tool to blame.

Whenever I try MAVEN_OPTS="--enable-preview" ./mvnw clean compile exec:java or ./gradlew clean compileJava run in my tiny repro project, it always ends with the error mentioned above.

Creating the jar with ./mvnw package or ./gradlew assemble works, the build finishes successfully (as in “no errors reported”).
And then trying to use it with java --enable-preview -jar ./path/to/artifact.jar ends up with the same error.

Even when I get rid of build tools like Maven or Gradle, and just rely on IntelliJ IDEA, the result is still the same: java.lang.ClassFormatError: Illegal field name "" in class ....

Manual execution of javac and java works without any issues, but any kind of automation doesn’t work.

I’m puzzled…

[To be continued.]

Language selector