$ bash configure --disable-cds-archive
$ jtreg -va test/jdk/tools/jlink/JLinkReproducibleTest.java(1/100)
STDERR:
java.lang.RuntimeException: assertEquals: expected -1 to equal 53610
at jdk.test.lib.Asserts.fail(Asserts.java:594)
at jdk.test.lib.Asserts.assertEquals(Asserts.java:205)
at jdk.test.lib.Asserts.assertEquals(Asserts.java:189)
at JLinkReproducibleTest.main(JLinkReproducibleTest.java:115)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:127)
at java.base/java.lang.Thread.run(Thread.java:831)
JavaTest Message: Test threw exception: java.lang.RuntimeException: assertEquals: expected -1 to equal 53610
$ cd JTwork/scratch/
$ jimage extract --dir module-a image-first/lib/modules && jimage extract --dir module-b image-second/lib/modules
$ javap -verbose -constants -s -l -private module-a/java.base/jdk/internal/module/SystemModules\$all.class > SystemModules$all.class.a && javap -verbose -constants -s -l -private module-b/java.base/jdk/internal/module/SystemModules\$all.class > SystemModules$all.class.b
$ diff -U0 SystemModules$all.class.a SystemModules$all.class.b
--- SystemModules.class.a 2020-12-25 11:12:49.552000000 +0800
+++ SystemModules.class.b 2020-12-25 11:12:39.440000000 +0800
@@ -1 +1 @@
-Classfile /home/hedongbo/myprojects/github/jdk.bak/test_result-JLinkReproducibleTest/jtwork-52/scratch/module-a/java.base/jdk/internal/module/SystemModules$all.class
+Classfile /home/hedongbo/myprojects/github/jdk.bak/test_result-JLinkReproducibleTest/jtwork-52/scratch/module-b/java.base/jdk/internal/module/SystemModules$all.class
@@ -3 +3 @@
- SHA-256 checksum b3e38cdf0f162d1d1e35ef2f43d28a961cd4b97c611a43e8e97064f8bcff41fb
+ SHA-256 checksum b2c4b6048130ad249f26d97b005e861b042c894bcd3e69c40a9a193c8674258d
@@ -628 +628 @@
- #617 = Integer 1300050017
+ #617 = Integer 2026721104
@@ -2744 +2744 @@
- 3592: ldc_w #617 // int 1300050017
+ 3592: ldc_w #617 // int 2026721104
We first discovered this problem in jdk11 (after backportJDK-8214230), and then I found that this problem will also occur when removing JDK-8202951 in jdk/jdk
The random value is md.hashCode() in the SystemModulesPlugin.SystemModulesPlugin.SystemModulesPlugin:putmoduledescriptor()
```
void putModuleDescriptor() {
mv.visitVarInsn(ALOAD, MD_VAR);
pushInt(mv, index);
mv.visitVarInsn(ALOAD, BUILDER_VAR);
mv.visitLdcInsn(md.hashCode()); // md.hashCode() is a random value
mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
"build", "(I)Ljava/lang/module/ModuleDescriptor;",
false);
mv.visitInsn(AASTORE);
}
```
When calculating md.hashCode(), it will use the hashcode of modifiers, requirements, exports and opens. However, these values have the Modifier field directly or indirectly (Modifier is an enum). Because the object hashcode of enum may be different in different JVMs, random values will be generated here.
```
public int hashCode() {
int hc = hash;
if (hc == 0) {
hc = name.hashCode();
hc = hc * 43 + Objects.hashCode(modifiers); // Set<Modifier> modifiers;
hc = hc * 43 + requires.hashCode(); // Set<Requires> requires
hc = hc * 43 + Objects.hashCode(packages);
hc = hc * 43 + exports.hashCode(); // Set<Exports> exports
hc = hc * 43 + opens.hashCode(); // Set<Opens> opens
hc = hc * 43 + uses.hashCode();
hc = hc * 43 + provides.hashCode();
hc = hc * 43 + Objects.hashCode(version);
hc = hc * 43 + Objects.hashCode(rawVersionString);
hc = hc * 43 + Objects.hashCode(mainClass);
if (hc == 0)
hc = -1;
hash = hc;
}
return hc;
}
```
In the case of this issue, the Modifier field in modifiers, exports and opens is null. Only requires has a Modifier field.
So, when I fixed the hashCode of requires in the code, the case in issue passed in 1,000 runs
$ jtreg -va test/jdk/tools/jlink/JLinkReproducibleTest.java(1/100)
STDERR:
java.lang.RuntimeException: assertEquals: expected -1 to equal 53610
at jdk.test.lib.Asserts.fail(Asserts.java:594)
at jdk.test.lib.Asserts.assertEquals(Asserts.java:205)
at jdk.test.lib.Asserts.assertEquals(Asserts.java:189)
at JLinkReproducibleTest.main(JLinkReproducibleTest.java:115)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:127)
at java.base/java.lang.Thread.run(Thread.java:831)
JavaTest Message: Test threw exception: java.lang.RuntimeException: assertEquals: expected -1 to equal 53610
$ cd JTwork/scratch/
$ jimage extract --dir module-a image-first/lib/modules && jimage extract --dir module-b image-second/lib/modules
$ javap -verbose -constants -s -l -private module-a/java.base/jdk/internal/module/SystemModules\$all.class > SystemModules$all.class.a && javap -verbose -constants -s -l -private module-b/java.base/jdk/internal/module/SystemModules\$all.class > SystemModules$all.class.b
$ diff -U0 SystemModules$all.class.a SystemModules$all.class.b
--- SystemModules.class.a 2020-12-25 11:12:49.552000000 +0800
+++ SystemModules.class.b 2020-12-25 11:12:39.440000000 +0800
@@ -1 +1 @@
-Classfile /home/hedongbo/myprojects/github/jdk.bak/test_result-JLinkReproducibleTest/jtwork-52/scratch/module-a/java.base/jdk/internal/module/SystemModules$all.class
+Classfile /home/hedongbo/myprojects/github/jdk.bak/test_result-JLinkReproducibleTest/jtwork-52/scratch/module-b/java.base/jdk/internal/module/SystemModules$all.class
@@ -3 +3 @@
- SHA-256 checksum b3e38cdf0f162d1d1e35ef2f43d28a961cd4b97c611a43e8e97064f8bcff41fb
+ SHA-256 checksum b2c4b6048130ad249f26d97b005e861b042c894bcd3e69c40a9a193c8674258d
@@ -628 +628 @@
- #617 = Integer 1300050017
+ #617 = Integer 2026721104
@@ -2744 +2744 @@
- 3592: ldc_w #617 // int 1300050017
+ 3592: ldc_w #617 // int 2026721104
We first discovered this problem in jdk11 (after backport
The random value is md.hashCode() in the SystemModulesPlugin.SystemModulesPlugin.SystemModulesPlugin:putmoduledescriptor()
```
void putModuleDescriptor() {
mv.visitVarInsn(ALOAD, MD_VAR);
pushInt(mv, index);
mv.visitVarInsn(ALOAD, BUILDER_VAR);
mv.visitLdcInsn(md.hashCode()); // md.hashCode() is a random value
mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER,
"build", "(I)Ljava/lang/module/ModuleDescriptor;",
false);
mv.visitInsn(AASTORE);
}
```
When calculating md.hashCode(), it will use the hashcode of modifiers, requirements, exports and opens. However, these values have the Modifier field directly or indirectly (Modifier is an enum). Because the object hashcode of enum may be different in different JVMs, random values will be generated here.
```
public int hashCode() {
int hc = hash;
if (hc == 0) {
hc = name.hashCode();
hc = hc * 43 + Objects.hashCode(modifiers); // Set<Modifier> modifiers;
hc = hc * 43 + requires.hashCode(); // Set<Requires> requires
hc = hc * 43 + Objects.hashCode(packages);
hc = hc * 43 + exports.hashCode(); // Set<Exports> exports
hc = hc * 43 + opens.hashCode(); // Set<Opens> opens
hc = hc * 43 + uses.hashCode();
hc = hc * 43 + provides.hashCode();
hc = hc * 43 + Objects.hashCode(version);
hc = hc * 43 + Objects.hashCode(rawVersionString);
hc = hc * 43 + Objects.hashCode(mainClass);
if (hc == 0)
hc = -1;
hash = hc;
}
return hc;
}
```
In the case of this issue, the Modifier field in modifiers, exports and opens is null. Only requires has a Modifier field.
So, when I fixed the hashCode of requires in the code, the case in issue passed in 1,000 runs
- relates to
-
JDK-8214230 Classes generated by SystemModulesPlugin.java are not reproducable
-
- Closed
-
-
JDK-8275509 ModuleDescriptor.hashCode isn't reproducible across builds
-
- Closed
-