Closed ReillyBrogan closed 1 year ago
@tajila fyi
This seems to be due to the computed hash code for ModuleDescriptor
objects. Several of the constituents of that computation are enum
objects (see ModuleDescriptor.Modifier
and ModuleDescriptor.*.Modifier
) which inherit hashCode()
from java.lang.Enum
which just delegates to java.lang.Object.hashCode()
.
Consider this small test program:
import java.lang.module.ModuleDescriptor;
public class ShowModifiers {
public static void main(String[] args) {
show(ModuleDescriptor.Exports.Modifier.class);
show(ModuleDescriptor.Modifier.class);
show(ModuleDescriptor.Opens.Modifier.class);
show(ModuleDescriptor.Requires.Modifier.class);
}
private static <T extends Enum<?>> void show(Class<T> cls) {
System.out.format("%s:%n", cls.getName());
for (Enum<?> constant : cls.getEnumConstants()) {
System.out.format(" %-12s -> 0x%08X%n", constant.name(), constant.hashCode());
}
}
}
When run with Temurin:
openjdk version "17" 2021-09-14
OpenJDK Runtime Environment Temurin-17+35 (build 17+35)
OpenJDK 64-Bit Server VM Temurin-17+35 (build 17+35, mixed mode, sharing)
the output consistently starts with
java.lang.module.ModuleDescriptor$Exports$Modifier:
SYNTHETIC -> 0x06B95977
MANDATED -> 0x7E9E5F8A
while OpenJ9 yields random hash codes:
java.lang.module.ModuleDescriptor$Exports$Modifier:
SYNTHETIC -> 0x86EF27A6
MANDATED -> 0xA423EDF5
or
java.lang.module.ModuleDescriptor$Exports$Modifier:
SYNTHETIC -> 0x8598B820
MANDATED -> 0xFC52C3F0
It seems our choices are either to make hash codes of enum literals consistent across runs, or alter the implementation of ModuleDescriptor.hashCode()
.
Even though openjdk says it's "Not an issue" or "Won't Fix" it seems they did make enum literal hash codes stable in jdk8u302-b08 or earlier builds.
This is fixed in Java 18; see
I'll handle this by back-porting the fix to Java 17 and Java 11.
Fixed via the two pull requests referenced above.
Not sure if the openj9 test suites use it, but if they do you could probably backport the related JDK-8276688 too.
I believe openj9 uses lists defined in https://github.com/adoptium/aqa-tests in files named ProblemList_openjdkN-openj9.txt
. None of those files exclude the JLinkReproducible*Test classes, so I think there's nothing more to be done here. @llxia Do you agree?
I've been trying to get jlink from openj9 to make bit-for-bit reproducible jlink images, however there seems to be an issue specific to openj9 that is causing the resultant images to be non-reproducible. This is easily noticeable with a test-case:
This returns with an output like the following:
Note that if more modules are used the result will be more binary differences in lib/modules.
Hotspot-based JDKs don't exhibit this behavior:
There will be no output which indicates that the two images are identical.
It would be great if this could be resolved so that we can update our build pipelines to be reproducible.