Am 2022-07-24 um 22:54 schrieb Andreas Sewe:
On 20.07.22 15:39, Karl Heinz Marbaise wrote:
On 20.07.22 13:04, Romain Manni-Bucau wrote:
> There is no need to use toolchain to run your build with JDK17 and
> create code for Java 8... you can use --release 8
> (<maven.compiler.release>8</maven.compiler.release>)...
>
> No toolchain needed.
So you run tests with java 17? This is not what you want if your prod is
in java 8, you can still get surprises so you need toolchain in your
build (same happen for compilation since bytecode is not 1-1, only
signatures).
First what kind of surprises?
Second can you show an example of different bytes codes?
Just a regular Maven user here, but I'll give you an example, Karl
Heinz, where testing against different Java versions was necessary to
avoid shipping a blocker bug -- even though the bytecode didn't differ
at all.
Some context: We maintain a couple of plug-ins for different IDEs
(Eclipse, IntelliJ, NetBeans). Each plugin needs to be compatible with a
whole range of IDE versions, as not all our users (can) use the latest
and greatest. And different IDE versions usually mean different Java
requirements, too.
In the case of the NetBeans plug-in (the same holds for Eclipse and
IntelliJ, but these are build with Gradle and Maven+Tycho, respectively,
rather than with plain Maven) this means that the plug-in needs to
target Java 8 at the lower end, as older versions of NetBeans don't even
run on the latest version of Java. Hence, we compile against Java 8.
However, we *also* occasionally test against newer versions of Java
(e.g., in our nightly builds) to catch errors like the following:
The plug-in classloader of NetBeans [1] (and IntelliJ [2], FWIW) does
not support multi-release JARs, which means that the following LOG4J2
statement fails when running on Java 9 or later.
private static final Logger LOGGER = LogManager.getLogger();
As the plug-in classloader does not support the multi-release
capabilities of the Log4J2 JAR, we end up in the Java 8 variant of
getLogger(), which no longer works under newer versions of Java. The
resulting ExceptionInInitializerError completely breaks our plug-in, but
this luckily has been found during testing -- running the tests with
Java 9 or later.
I hope this example was useful to the discussion at hand.
Now, at the moment we run Maven itself with Java 17 (as it speeds up our
builds) and use toolchains to compile *and* test against Java 8. During
our nightly build, however, we also pass in a system property which
selects a different toolchain (ATM, Java 11).
This works, but is not ideal, as our nightly sanity build not only tests
against Java 11 but also builds against it; both maven-compiler-plugin
and maven-surefire-plugin use the *same* toolchain. Unfortunately, this
means that we don't have a guarantee that the test against Java 11 use
the same bytecode that we ship, since the nightly build compiles with
the Java 11 but we have to ship the code compiled against Java 8 (i.e.,
our lowest denominator).
In an ideal world, our setup would look like this:
- mvn: Runs with Java 17
- maven-compiler-plugin: --release 8
- maven-surefire-plugin: a Java 8/11/17 toolchain, selected by system
property
At the moment, we are not there yet, as we cannot use --release, as
there cannot be separate toolchains for compilation and test. If that
were to change with Maven 4, that would be great, of course.
Hope this helps.
As I said. Such an example and a move to Java 17 would cause just
friction without any lubricant.