[Bug] javac gives non-deterministic output (for sealed interface with records)

Przemek Bielicki pbielicki at gmail.com
Mon Dec 18 08:50:48 UTC 2023


Hey Folks,

I'm not 100% sure it's the best idea to post it here but I have no access
to the JDK JIRA (yet?) 🙈

Last week I had a huge headache because of a bug I discovered in the Java
compiler - Eclipse Temurin OpenJDK 64-Bit Server VM 17.0.9+9 (mixed mode,
sharing). I'm pretty certain it's a bug because my expectation is that the
compiler MUST produce deterministic output of the compiled classes - at
least when the JDK version is the same.

*## Expected behavior*

Java compiler produces deterministic output i.e compiled byte code is
exactly the same (SHA-wise) and is independent of the operating system
type, version and other variables.

*## Bug description*

When compiling 1700+ classes in one of our modules on different CI agents
(with exact same JDK version) I noticed intermittent SHA differences (of
the compiled classes) that originated from a single class (the
attached GradleExecGraphNodeExecutionInfo.java file.) It's a
sealed interface and it uses records - I have an impression that using
these two in conjunction plays a role here.

I also attach the compiled bytecode coming from two different CI agents.
If you compare the bytecode you will notice this:
[image: image.png]
The only difference (if the image is not displayed correctly) is that two
same bytes (at the 0x440 position) switch the order depending on where the
class is compiled. I didn't check the meaning of those bytes - I hope you
can help here.

"javap -c -l -private" shows that the output is exactly the same (but it
isn't).

The only difference between the CI nodes is the Linux kernel version (Linux
5.4.0-*166*-generic (amd64) vs Linux 5.4.0-*167*-generic (amd64). I was
able to reproduce this behavior consistently when I compiled this module on
different CI agents with the same difference in the Linux kernel.
Here's the screen from Develocity showing the diff in the infrastructure.
[image: image.png]

I tried to reproduce this problem with the minimal reproducer (by
extracting the sealed interface outside of the big module) but I failed
here. The produced byte code was the same.

Please let me know if you need to check sources of the other classes
referenced by this sealed interface. I'd need to get an approval before
sharing them publicly.

Cheers,
Przemek
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20231218/29d01f71/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image.png
Type: image/png
Size: 9238 bytes
Desc: not available
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20231218/29d01f71/image-0002.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image.png
Type: image/png
Size: 165378 bytes
Desc: not available
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20231218/29d01f71/image-0003.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: GradleExecGraphNodeExecutionInfo.java
Type: application/octet-stream
Size: 2017 bytes
Desc: not available
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20231218/29d01f71/GradleExecGraphNodeExecutionInfo-0001.java>


More information about the compiler-dev mailing list