Library authors: rebuild on 2.12.7 to improve callability from Java on JDK 11

Heads up to library authors who care whether their libraries are usable from Java.

Normally it doesn’t much matter what Scala version your library is built with, but https://github.com/scala/scala/pull/6531 is unusual, it requires libraries be rebuilt on 2.12.7 to get the benefit of the bugfix.

A real example of library users hitting this problem happened on Akka, https://github.com/akka/akka/issues/25777 (and see also https://github.com/scala/bug/issues/11061). For Java users on JDK 11, an Akka method became uncallable from Java. The problem will be fixed once an Akka version is published that was built with 2.12.7.

2 Likes

I looked at the references, but I’m still confused about exactly what caused the problem. Is there a brief explanation of why the generated code worked with JDK < 11 but breaks with JDK 11?

There are multiple pieces to this:

  1. why the code the compiler used to generate was wrong
  2. how wrong code came to be generated
  3. why it worked anyway before but broke in JDK 11

not sure which you’re wondering about, maybe all three. To really completely explain everything about 1 and 2 (including answering questions like “what are bridge methods?” and “what are static forwarders?”) would take a while, can you be more specific about where you’re losing the trail…?

As for 3, I haven’t seen any explanation of that (or e.g. a link to a ticket). But given that the bytecode was incorrect, it’s certainly fair for the JVM to handle it more strictly.

It’s worth noting that the code produced by Scala < 2.12.7 does not really “break” the JDK. What happens is that when using a Scala library in a Java codebase, compiling this codebase with javac >= 11 might fail with ambiguous overload errors if the Scala library was compiled with Scala < 2.12.7.

1 Like

Yes, well put.

Also, I don’t actually know whether anything changed at the JVM level, or only in javac. Perhaps it’s only javac that became more strict?

The title just says JDK 11, which includes javac as much as the JVM :wink:

why it worked anyway before but broke in JDK 11

That’s actually the one I was curious about. As I understand it, there were two methods being generated that had the same signature except for the return type. That’s definitely not legal in Java the language in any version, so I wonder why the behavior changed now.

Further investigation leads me to suspect a connection to JEP 181, “Nest-Based Access Control”, which also involves bridge methods. But I’m just guessing.