Hi,
I’m umming and ahhing about what version of Java bytecode to target for a Scala library…
I maintain a library (Americium) that is intended to be used by both Java and Scala developers.
It has two APIs, one for Java folks using Java collections, Java options, Java function types etc and another for Scala using the obvious Scala equivalents. It’s expected that most clients will pick a single API entry point and work with that, although it is possible to get one form of the API from another to mix-and-match. Cool.
For a long time, I built this library using an explicit version of the Java language, wiring it into the build via javacOptions ++= Seq("-source", javaVersion, "-target", javaVersion)
.
This started off as 1.8 aka Java 8, then went to 1.9 / Java 9 to support some Java test code.
In the meantime, I’ve been happily building using whatever the latest and greatest JDK is - up to 21 for day to day work, with some experimental work on 22.
I was under the impression that setting javacOptions
would affect the Scala code generation, but it’s recently come to light that the published JARs are a mixture of bytecode for Java 8 (classfile version 52) from the Scala sources and the bytecode version explicitly set by javacOptions
, namely for Java 9 (classfile version 53).
To make matters worse, both the production and test Java and Scala code have little dependencies here and there on Java 11 SDK features that have happily compiled because I’ve used a recent JDK to develop with. I’m not completely sure what’s going on there, but it seems the bytecode is generated as described above, but presumably with an implicit dependency on a more recent JDK runtime library. There is even a dependency in some test code on Java 15 that’s crept in.
I discovered this recently after wiring in the java-output-version
into scalacOptions
, thinking this would just be a nice ‘conform with style’ change and then finding that a downstream project won’t build against the latest published library - the Scala bytecode has now jumped up to match the Java bytecode version. Playing around the now consistently set Java version then revealed the implicit JDK runtime dependencies.
What a mess!
Anyway, I’ve made a release that sets the Java version to 17 LTS, switched to doing builds on GitHub and jemmied the Github build to use JDK 17 to get things in order.
I’m taking the view that chasing JDK 8 isn’t worthwhile, as it is likely that shops using Java 8 are either running unmaintained legacy code or have an overly cautious / conservative attitude which would make it unlikely that they would want to use a new library anyway. However, JDK 17 is still fairly recent, and the only report with numbers I’ve seen indicates a split in adoption between JDK 11 LTS and JDK 17 LTS, so perhaps I’m being a bit draconian in expecting users to bump up to 17.
I’m interested to hear from folk responsible for production code as to what they would do in this position or expect as users…