We want the JDK build to be "reproducible". This means that when building the JDK from the same source code, we want to (as much as possible) generate the exact same set of binaries that are bit-by-bit identical. The is useful in validating the JDK build process.
In CDS, after JDK-8241071 (Generation of classes.jsa with -Xshare:dump is not deterministic), running "java -Xshare:dump" twice should generate the exact same classes.jsa.
However, if you make changes in CDS, sometimes reproducibility may be broken, causing the DeterministicDump.java may fail. The usual causes are:
- You didn't sort objects before writing. See some notes here.
- The objects contains random data that varies from run to run of the JVM.
To debug the failure, use the following script and gdb:
Often time we break reproducibility by writing an unprocessed native pointer into the archive. For example, InstanceKlass::_package_entry should be set to NULL before the InstanceKlass is copied. We can disable this by:
Running compare_cds_dump.sh shows the following output:
The first few lines are just differences in the CRC values. The first real difference appears at offset 0x000082f0 in the JSA file.
To find out what's written into this location, we first need to find out the address of the above offset. The can be found from these lines in 1.txt
This basically means that the address for offset X is 0x0000000800000000 + X - 0x1000. I.e., the address for offset 0x000082f0 is 0x8000072f0.
We can now run -Xshare:dump inside gdb:
So this happens when an object is being copied into the CDS archive:
We can figure out the type of the object by doing this:
p is the location of the copy of the InstanceKlass, and the offending address 0x8000072f0 is offset 224 into this copy, which is the as the field offset of InstanceKlass::_package_entry.
From the above, we can conclude that:
- The problem is caused by InstanceKlass::_package_entry
- The offending value (0x7ffff0205a90) looks like an object allocated from the C-HEAP on Linux. C-HEAP allocations vary from run to run of the JVM. That's why we get two different JSA files from two -Xshare:dump runs.