< prev index next >

src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java

Print this page

        

@@ -66,16 +66,22 @@
     public static class ModuleAttribute extends Attribute {
         private static final JavaLangModuleAccess JLMA
             = SharedSecrets.getJavaLangModuleAccess();
 
         private ModuleDescriptor descriptor;
+        private Version replacementVersion;
 
         public ModuleAttribute(ModuleDescriptor descriptor) {
             super(MODULE);
             this.descriptor = descriptor;
         }
 
+        public ModuleAttribute(Version v) {
+            super(MODULE);
+            this.replacementVersion = v;
+        }
+
         public ModuleAttribute() {
             super(MODULE);
         }
 
         @Override

@@ -84,79 +90,104 @@
                                  int len,
                                  char[] buf,
                                  int codeOff,
                                  Label[] labels)
         {
-            ModuleAttribute attr = new ModuleAttribute();
-
-            // module_name
-            String mn = cr.readUTF8(off, buf).replace('/', '.');
+            // module_name (CONSTANT_Module_info)
+            String mn = cr.readModule(off, buf);
             off += 2;
 
             // module_flags
             int module_flags = cr.readUnsignedShort(off);
             boolean open = ((module_flags & ACC_OPEN) != 0);
+            boolean synthetic = ((module_flags & ACC_SYNTHETIC) != 0);
             off += 2;
 
-            ModuleDescriptor.Builder builder;
-            if (open) {
-                builder = JLMA.newOpenModuleBuilder(mn, false);
-            } else {
-                builder = JLMA.newModuleBuilder(mn, false);
+            ModuleDescriptor.Builder builder = JLMA.newModuleBuilder(mn,
+                                                                     false,
+                                                                     open,
+                                                                     synthetic);
+
+            // module_version
+            String module_version = cr.readUTF8(off, buf);
+            off += 2;
+            if (replacementVersion != null) {
+                builder.version(replacementVersion);
+            } else if (module_version != null) {
+                builder.version(module_version);
             }
 
             // requires_count and requires[requires_count]
             int requires_count = cr.readUnsignedShort(off);
             off += 2;
             for (int i=0; i<requires_count; i++) {
-                String dn = cr.readUTF8(off, buf).replace('/', '.');
-                int flags = cr.readUnsignedShort(off + 2);
+                // CONSTANT_Module_info
+                String dn = cr.readModule(off, buf);
+                off += 2;
+
+                // requires_flags
+                int requires_flags = cr.readUnsignedShort(off);
+                off += 2;
                 Set<Requires.Modifier> mods;
-                if (flags == 0) {
+                if (requires_flags == 0) {
                     mods = Collections.emptySet();
                 } else {
                     mods = new HashSet<>();
-                    if ((flags & ACC_TRANSITIVE) != 0)
+                    if ((requires_flags & ACC_TRANSITIVE) != 0)
                         mods.add(Requires.Modifier.TRANSITIVE);
-                    if ((flags & ACC_STATIC_PHASE) != 0)
+                    if ((requires_flags & ACC_STATIC_PHASE) != 0)
                         mods.add(Requires.Modifier.STATIC);
-                    if ((flags & ACC_SYNTHETIC) != 0)
+                    if ((requires_flags & ACC_SYNTHETIC) != 0)
                         mods.add(Requires.Modifier.SYNTHETIC);
-                    if ((flags & ACC_MANDATED) != 0)
+                    if ((requires_flags & ACC_MANDATED) != 0)
                         mods.add(Requires.Modifier.MANDATED);
                 }
+
+
+                // requires_version
+                Version compiledVersion = null;
+                String requires_version = cr.readUTF8(off, buf);
+                off += 2;
+                if (requires_version != null) {
+                    compiledVersion = Version.parse(requires_version);
+                }
+
+                if (compiledVersion == null) {
                 builder.requires(mods, dn);
-                off += 4;
+                } else {
+                    builder.requires(mods, dn, compiledVersion);
+                }
             }
 
             // exports_count and exports[exports_count]
             int exports_count = cr.readUnsignedShort(off);
             off += 2;
             if (exports_count > 0) {
                 for (int i=0; i<exports_count; i++) {
-                    String pkg = cr.readUTF8(off, buf).replace('/', '.');
+                    // CONSTANT_Package_info
+                    String pkg = cr.readPackage(off, buf).replace('/', '.');
                     off += 2;
 
-                    int flags = cr.readUnsignedShort(off);
+                    int exports_flags = cr.readUnsignedShort(off);
                     off += 2;
                     Set<Exports.Modifier> mods;
-                    if (flags == 0) {
+                    if (exports_flags == 0) {
                         mods = Collections.emptySet();
                     } else {
                         mods = new HashSet<>();
-                        if ((flags & ACC_SYNTHETIC) != 0)
+                        if ((exports_flags & ACC_SYNTHETIC) != 0)
                             mods.add(Exports.Modifier.SYNTHETIC);
-                        if ((flags & ACC_MANDATED) != 0)
+                        if ((exports_flags & ACC_MANDATED) != 0)
                             mods.add(Exports.Modifier.MANDATED);
                     }
 
                     int exports_to_count = cr.readUnsignedShort(off);
                     off += 2;
                     if (exports_to_count > 0) {
                         Set<String> targets = new HashSet<>();
                         for (int j=0; j<exports_to_count; j++) {
-                            String t = cr.readUTF8(off, buf).replace('/', '.');
+                            String t = cr.readModule(off, buf);
                             off += 2;
                             targets.add(t);
                         }
                         builder.exports(mods, pkg, targets);
                     } else {

@@ -168,32 +199,33 @@
             // opens_count and opens[opens_count]
             int open_count = cr.readUnsignedShort(off);
             off += 2;
             if (open_count > 0) {
                 for (int i=0; i<open_count; i++) {
-                    String pkg = cr.readUTF8(off, buf).replace('/', '.');
+                    // CONSTANT_Package_info
+                    String pkg = cr.readPackage(off, buf).replace('/', '.');
                     off += 2;
 
-                    int flags = cr.readUnsignedShort(off);
+                    int opens_flags = cr.readUnsignedShort(off);
                     off += 2;
                     Set<Opens.Modifier> mods;
-                    if (flags == 0) {
+                    if (opens_flags == 0) {
                         mods = Collections.emptySet();
                     } else {
                         mods = new HashSet<>();
-                        if ((flags & ACC_SYNTHETIC) != 0)
+                        if ((opens_flags & ACC_SYNTHETIC) != 0)
                             mods.add(Opens.Modifier.SYNTHETIC);
-                        if ((flags & ACC_MANDATED) != 0)
+                        if ((opens_flags & ACC_MANDATED) != 0)
                             mods.add(Opens.Modifier.MANDATED);
                     }
 
                     int opens_to_count = cr.readUnsignedShort(off);
                     off += 2;
                     if (opens_to_count > 0) {
                         Set<String> targets = new HashSet<>();
                         for (int j=0; j<opens_to_count; j++) {
-                            String t = cr.readUTF8(off, buf).replace('/', '.');
+                            String t = cr.readModule(off, buf);
                             off += 2;
                             targets.add(t);
                         }
                         builder.opens(mods, pkg, targets);
                     } else {

@@ -230,12 +262,11 @@
                     }
                     builder.provides(service, providers);
                 }
             }
 
-            attr.descriptor = builder.build();
-            return attr;
+            return new ModuleAttribute(builder.build());
         }
 
         @Override
         protected ByteVector write(ClassWriter cw,
                                    byte[] code,

@@ -246,81 +277,98 @@
             assert descriptor != null;
             ByteVector attr = new ByteVector();
 
             // module_name
             String mn = descriptor.name();
-            int module_name_index = cw.newUTF8(mn.replace('.', '/'));
+            int module_name_index = cw.newModule(mn);
             attr.putShort(module_name_index);
 
             // module_flags
             int module_flags = 0;
             if (descriptor.isOpen())
                 module_flags |= ACC_OPEN;
             if (descriptor.isSynthetic())
                 module_flags |= ACC_SYNTHETIC;
             attr.putShort(module_flags);
 
+            // module_version
+            Version v = descriptor.version().orElse(null);
+            if (v == null) {
+                attr.putShort(0);
+            } else {
+                int module_version_index = cw.newUTF8(v.toString());
+                attr.putShort(module_version_index);
+            }
+
             // requires_count
             attr.putShort(descriptor.requires().size());
 
             // requires[requires_count]
-            for (Requires md : descriptor.requires()) {
-                String dn = md.name();
-                int flags = 0;
-                if (md.modifiers().contains(Requires.Modifier.TRANSITIVE))
-                    flags |= ACC_TRANSITIVE;
-                if (md.modifiers().contains(Requires.Modifier.STATIC))
-                    flags |= ACC_STATIC_PHASE;
-                if (md.modifiers().contains(Requires.Modifier.SYNTHETIC))
-                    flags |= ACC_SYNTHETIC;
-                if (md.modifiers().contains(Requires.Modifier.MANDATED))
-                    flags |= ACC_MANDATED;
-                int index = cw.newUTF8(dn.replace('.', '/'));
-                attr.putShort(index);
-                attr.putShort(flags);
+            for (Requires r : descriptor.requires()) {
+                int requires_index = cw.newModule(r.name());
+                attr.putShort(requires_index);
+
+                int requires_flags = 0;
+                if (r.modifiers().contains(Requires.Modifier.TRANSITIVE))
+                    requires_flags |= ACC_TRANSITIVE;
+                if (r.modifiers().contains(Requires.Modifier.STATIC))
+                    requires_flags |= ACC_STATIC_PHASE;
+                if (r.modifiers().contains(Requires.Modifier.SYNTHETIC))
+                    requires_flags |= ACC_SYNTHETIC;
+                if (r.modifiers().contains(Requires.Modifier.MANDATED))
+                    requires_flags |= ACC_MANDATED;
+                attr.putShort(requires_flags);
+
+                int requires_version_index;
+                v = r.compiledVersion().orElse(null);
+                if (v == null) {
+                    requires_version_index = 0;
+                } else {
+                    requires_version_index = cw.newUTF8(v.toString());
+                }
+                attr.putShort(requires_version_index);
             }
 
             // exports_count and exports[exports_count];
             attr.putShort(descriptor.exports().size());
             for (Exports e : descriptor.exports()) {
                 String pkg = e.source().replace('.', '/');
-                attr.putShort(cw.newUTF8(pkg));
+                attr.putShort(cw.newPackage(pkg));
 
-                int flags = 0;
+                int exports_flags = 0;
                 if (e.modifiers().contains(Exports.Modifier.SYNTHETIC))
-                    flags |= ACC_SYNTHETIC;
+                    exports_flags |= ACC_SYNTHETIC;
                 if (e.modifiers().contains(Exports.Modifier.MANDATED))
-                    flags |= ACC_MANDATED;
-                attr.putShort(flags);
+                    exports_flags |= ACC_MANDATED;
+                attr.putShort(exports_flags);
 
                 if (e.isQualified()) {
                     Set<String> ts = e.targets();
                     attr.putShort(ts.size());
-                    ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
+                    ts.forEach(target -> attr.putShort(cw.newModule(target)));
                 } else {
                     attr.putShort(0);
                 }
             }
 
-
             // opens_counts and opens[opens_counts]
             attr.putShort(descriptor.opens().size());
             for (Opens obj : descriptor.opens()) {
                 String pkg = obj.source().replace('.', '/');
-                attr.putShort(cw.newUTF8(pkg));
+                attr.putShort(cw.newPackage(pkg));
 
-                int flags = 0;
+                int opens_flags = 0;
                 if (obj.modifiers().contains(Opens.Modifier.SYNTHETIC))
-                    flags |= ACC_SYNTHETIC;
+                    opens_flags |= ACC_SYNTHETIC;
                 if (obj.modifiers().contains(Opens.Modifier.MANDATED))
-                    flags |= ACC_MANDATED;
-                attr.putShort(flags);
+                    opens_flags |= ACC_MANDATED;
+                attr.putShort(opens_flags);
 
                 if (obj.isQualified()) {
                     Set<String> ts = obj.targets();
                     attr.putShort(ts.size());
-                    ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
+                    ts.forEach(target -> attr.putShort(cw.newModule(target)));
                 } else {
                     attr.putShort(0);
                 }
             }
 

@@ -367,11 +415,11 @@
      *   u2 attribute_name_index;
      *   u4 attribute_length;
      *
      *   // the number of entries in the packages table
      *   u2 packages_count;
-     *   { // index to CONSTANT_CONSTANT_utf8_info structure with the package name
+     *   { // index to CONSTANT_Package_info structure with the package name
      *     u2 package_index
      *   } packages[package_count];
      *
      * }</pre>
      */

@@ -400,11 +448,11 @@
             off += 2;
 
             // packages
             Set<String> packages = new HashSet<>();
             for (int i=0; i<package_count; i++) {
-                String pkg = cr.readUTF8(off, buf).replace('/', '.');
+                String pkg = cr.readPackage(off, buf).replace('/', '.');
                 packages.add(pkg);
                 off += 2;
             }
 
             return new ModulePackagesAttribute(packages);

@@ -425,73 +473,18 @@
             attr.putShort(packages.size());
 
             // packages
             packages.stream()
                 .map(p -> p.replace('.', '/'))
-                .forEach(p -> attr.putShort(cw.newUTF8(p)));
+                .forEach(p -> attr.putShort(cw.newPackage(p)));
 
             return attr;
         }
 
     }
 
     /**
-     * ModuleVersion attribute.
-     *
-     * <pre> {@code
-     *
-     * ModuleVersion_attribute {
-     *   // index to CONSTANT_utf8_info structure in constant pool representing
-     *   // the string "ModuleVersion"
-     *   u2 attribute_name_index;
-     *   u4 attribute_length;
-     *
-     *   // index to CONSTANT_CONSTANT_utf8_info structure with the version
-     *   u2 version_index;
-     * }
-     *
-     * } </pre>
-     */
-    public static class ModuleVersionAttribute extends Attribute {
-        private final Version version;
-
-        public ModuleVersionAttribute(Version version) {
-            super(MODULE_VERSION);
-            this.version = version;
-        }
-
-        public ModuleVersionAttribute() {
-            this(null);
-        }
-
-        @Override
-        protected Attribute read(ClassReader cr,
-                                 int off,
-                                 int len,
-                                 char[] buf,
-                                 int codeOff,
-                                 Label[] labels)
-        {
-            String value = cr.readUTF8(off, buf);
-            return new ModuleVersionAttribute(Version.parse(value));
-        }
-
-        @Override
-        protected ByteVector write(ClassWriter cw,
-                                   byte[] code,
-                                   int len,
-                                   int maxStack,
-                                   int maxLocals)
-        {
-            ByteVector attr = new ByteVector();
-            int index = cw.newUTF8(version.toString());
-            attr.putShort(index);
-            return attr;
-        }
-    }
-
-    /**
      * ModuleMainClass attribute.
      *
      * <pre> {@code
      *
      * MainClass_attribute {

@@ -524,11 +517,11 @@
                                  int len,
                                  char[] buf,
                                  int codeOff,
                                  Label[] labels)
         {
-            String value = cr.readClass(off, buf);
+            String value = cr.readClass(off, buf).replace('/', '.');
             return new ModuleMainClassAttribute(value);
         }
 
         @Override
         protected ByteVector write(ClassWriter cw,

@@ -536,11 +529,11 @@
                                    int len,
                                    int maxStack,
                                    int maxLocals)
         {
             ByteVector attr = new ByteVector();
-            int index = cw.newClass(mainClass);
+            int index = cw.newClass(mainClass.replace('.', '/'));
             attr.putShort(index);
             return attr;
         }
     }
 

@@ -553,15 +546,15 @@
      *   // index to CONSTANT_utf8_info structure in constant pool representing
      *   // the string "ModuleTarget"
      *   u2 attribute_name_index;
      *   u4 attribute_length;
      *
-     *   // index to CONSTANT_CONSTANT_utf8_info structure with the OS name
+     *   // index to CONSTANT_utf8_info structure with the OS name
      *   u2 os_name_index;
-     *   // index to CONSTANT_CONSTANT_utf8_info structure with the OS arch
+     *   // index to CONSTANT_utf8_info structure with the OS arch
      *   u2 os_arch_index
-     *   // index to CONSTANT_CONSTANT_utf8_info structure with the OS version
+     *   // index to CONSTANT_utf8_info structure with the OS version
      *   u2 os_version_index;
      * }
      *
      * } </pre>
      */

@@ -654,11 +647,11 @@
      *   // index to CONSTANT_utf8_info structure with algorithm name
      *   u2 algorithm_index;
      *
      *   // the number of entries in the hashes table
      *   u2 hashes_count;
-     *   {   u2 module_name_index
+     *   {   u2 module_name_index (index to CONSTANT_Module_info structure)
      *       u2 hash_length;
      *       u1 hash[hash_length];
      *   } hashes[hashes_count];
      *
      * } </pre>

@@ -689,11 +682,11 @@
             int hashes_count = cr.readUnsignedShort(off);
             off += 2;
 
             Map<String, byte[]> map = new HashMap<>();
             for (int i=0; i<hashes_count; i++) {
-                String mn = cr.readUTF8(off, buf).replace('/', '.');
+                String mn = cr.readModule(off, buf);
                 off += 2;
 
                 int hash_length = cr.readUnsignedShort(off);
                 off += 2;
                 byte[] hash = new byte[hash_length];

@@ -726,11 +719,11 @@
             attr.putShort(names.size());
 
             for (String mn : names) {
                 byte[] hash = hashes.hashFor(mn);
                 assert hash != null;
-                attr.putShort(cw.newUTF8(mn.replace('.', '/')));
+                attr.putShort(cw.newModule(mn));
 
                 attr.putShort(hash.length);
                 for (byte b: hash) {
                     attr.putByte(b);
                 }

@@ -738,6 +731,60 @@
 
             return attr;
         }
     }
 
+    /**
+     *  ModuleResolution_attribute {
+     *    u2 attribute_name_index;    // "ModuleResolution"
+     *    u4 attribute_length;        // 2
+     *    u2 resolution_flags;
+     *
+     *  The value of the resolution_flags item is a mask of flags used to denote
+     *  properties of module resolution. The flags are as follows:
+     *
+     *   // Optional
+     *   0x0001 (DO_NOT_RESOLVE_BY_DEFAULT)
+     *
+     *   // At most one of:
+     *   0x0002 (WARN_DEPRECATED)
+     *   0x0004 (WARN_DEPRECATED_FOR_REMOVAL)
+     *   0x0008 (WARN_INCUBATING)
+     */
+    static class ModuleResolutionAttribute extends Attribute {
+        private final int value;
+
+        ModuleResolutionAttribute() {
+            super(MODULE_RESOLUTION);
+            value = 0;
+        }
+
+        ModuleResolutionAttribute(int value) {
+            super(MODULE_RESOLUTION);
+            this.value = value;
+        }
+
+        @Override
+        protected Attribute read(ClassReader cr,
+                                 int off,
+                                 int len,
+                                 char[] buf,
+                                 int codeOff,
+                                 Label[] labels)
+        {
+            int flags = cr.readUnsignedShort(off);
+            return new ModuleResolutionAttribute(flags);
+        }
+
+        @Override
+        protected ByteVector write(ClassWriter cw,
+                                   byte[] code,
+                                   int len,
+                                   int maxStack,
+                                   int maxLocals)
+        {
+            ByteVector attr = new ByteVector();
+            attr.putShort(value);
+            return attr;
+        }
+    }
 }
< prev index next >