Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8275731

CDS archived enums objects are recreated at runtime

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P3
    • 19
    • 18
    • hotspot
    • b12

    Description

      As reported in https://mail.openjdk.java.net/pipermail/core-libs-dev/2021-October/082709.html

      The static constructors of enum classes are executed at both CDS dump time and run time. E.g.,

          public enum Modifier {
              OPEN,
          }

      The Modifier::<clinit> method is a synthetic method created by javac. It essentially does this:

          public static final Modifier OPEN = new Modifier("OPEN");

      If a reference of Modifier.OPEN is stored inside the CDS archived heap, it will be different than the value of Modifier.OPEN that is re-created at runtime by the execution of Modifier.<clinit>

      ==============================
      import java.lang.module.*;
      import java.io.*;
      import java.util.*;

      public class EnumEquality {

          public static void main(final String[] args) throws Exception {
              String moduleName = "java.sql";
              // load the "java.sql" module from boot layer
              Optional<Module> bootModule = ModuleLayer.boot().findModule(moduleName);
              if (bootModule.isEmpty()) {
                  throw new RuntimeException(moduleName + " module is missing in boot layer");
              }
              ModuleDescriptor m1 = bootModule.get().getDescriptor();
              // now recreate the same module using the ModuleDescriptor.read on the module's module-info.class
              ModuleDescriptor m2;
              try (InputStream moduleInfo = bootModule.get().getResourceAsStream("module-info.class")) {
                  if (moduleInfo == null) {
                      throw new RuntimeException("Could not locate module-info.class in " + moduleName + " module");
                  }
                  // this will internally use a ModuleDescriptor.Builder to construct the ModuleDescriptor
                  m2 = ModuleDescriptor.read(moduleInfo);
              }
              if (!m1.equals(m2)) {
                  // root cause - the enums aren't "equal"
                  for (ModuleDescriptor.Requires r1 : m1.requires()) {
                      if (r1.name().equals("java.base")) {
                          for (ModuleDescriptor.Requires r2 : m2.requires()) {
                              if (r2.name().equals("java.base")) {
                                  System.out.println("Modifiers r1 " + r1.modifiers() + " r2 " + r2.modifiers()
                                      + " --> equals? " + r1.modifiers().equals(r2.modifiers()));
                              }
                          }
                      }
                  }

                  throw new RuntimeException("ModuleDescriptor(s) aren't equal: \n" + m1 + "\n" + m2);
              }
              System.out.println("Success");
          }
      }




      Attachments

        Issue Links

          Activity

            People

              iklam Ioi Lam
              iklam Ioi Lam
              Votes:
              0 Vote for this issue
              Watchers:
              8 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: