8186236: ModuleInfoExtender should be ASM6 aware
Reviewed-by: ksrini, mchung, sundar
--- a/src/java.base/share/classes/java/lang/Module.java Thu Nov 02 13:18:23 2017 -0700
+++ b/src/java.base/share/classes/java/lang/Module.java Thu Nov 02 13:20:21 2017 -0700
@@ -57,8 +57,6 @@
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.ClassLoaders;
-import jdk.internal.misc.JavaLangAccess;
-import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.IllegalAccessLogger;
import jdk.internal.module.ModuleLoaderMap;
import jdk.internal.module.ServicesCatalog;
@@ -68,6 +66,7 @@
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
@@ -1432,7 +1431,7 @@
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ ClassWriter.COMPUTE_FRAMES);
- ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) {
+ ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) {
@Override
public void visit(int version,
int access,
@@ -1458,6 +1457,11 @@
public void visitAttribute(Attribute attr) {
// drop non-annotation attributes
}
+ @Override
+ public ModuleVisitor visitModule(String name, int flags, String version) {
+ // drop Module attribute
+ return null;
+ }
};
ClassReader cr = new ClassReader(in);
--- a/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java Thu Nov 02 13:18:23 2017 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,765 +0,0 @@
-/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.module;
-
-import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Builder;
-import java.lang.module.ModuleDescriptor.Requires;
-import java.lang.module.ModuleDescriptor.Exports;
-import java.lang.module.ModuleDescriptor.Opens;
-import java.lang.module.ModuleDescriptor.Provides;
-import java.lang.module.ModuleDescriptor.Version;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import jdk.internal.misc.JavaLangModuleAccess;
-import jdk.internal.misc.SharedSecrets;
-import jdk.internal.org.objectweb.asm.Attribute;
-import jdk.internal.org.objectweb.asm.ByteVector;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Label;
-import static jdk.internal.module.ClassFileConstants.*;
-
-
-/**
- * Provides ASM implementations of {@code Attribute} to read and write the
- * class file attributes in a module-info class file.
- */
-
-public final class ClassFileAttributes {
-
- private ClassFileAttributes() { }
-
- /**
- * Module_attribute {
- * // See lang-vm.html for details.
- * }
- */
- 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
- protected Attribute read(ClassReader cr,
- int off,
- int len,
- char[] buf,
- int codeOff,
- Label[] labels)
- {
- // module_name (CONSTANT_Module_info)
- String mn = cr.readModule(off, buf);
- off += 2;
-
- // module_flags
- int module_flags = cr.readUnsignedShort(off);
- off += 2;
-
- Set<ModuleDescriptor.Modifier> modifiers = new HashSet<>();
- if ((module_flags & ACC_OPEN) != 0)
- modifiers.add(ModuleDescriptor.Modifier.OPEN);
- if ((module_flags & ACC_SYNTHETIC) != 0)
- modifiers.add(ModuleDescriptor.Modifier.SYNTHETIC);
- if ((module_flags & ACC_MANDATED) != 0)
- modifiers.add(ModuleDescriptor.Modifier.MANDATED);
-
- Builder builder = JLMA.newModuleBuilder(mn, false, modifiers);
-
- // 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++) {
- // 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 (requires_flags == 0) {
- mods = Collections.emptySet();
- } else {
- mods = new HashSet<>();
- if ((requires_flags & ACC_TRANSITIVE) != 0)
- mods.add(Requires.Modifier.TRANSITIVE);
- if ((requires_flags & ACC_STATIC_PHASE) != 0)
- mods.add(Requires.Modifier.STATIC);
- if ((requires_flags & ACC_SYNTHETIC) != 0)
- mods.add(Requires.Modifier.SYNTHETIC);
- if ((requires_flags & ACC_MANDATED) != 0)
- mods.add(Requires.Modifier.MANDATED);
- }
-
- // requires_version
- String requires_version = cr.readUTF8(off, buf);
- off += 2;
- if (requires_version == null) {
- builder.requires(mods, dn);
- } else {
- JLMA.requires(builder, mods, dn, requires_version);
- }
- }
-
- // 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++) {
- // CONSTANT_Package_info
- String pkg = cr.readPackage(off, buf).replace('/', '.');
- off += 2;
-
- int exports_flags = cr.readUnsignedShort(off);
- off += 2;
- Set<Exports.Modifier> mods;
- if (exports_flags == 0) {
- mods = Collections.emptySet();
- } else {
- mods = new HashSet<>();
- if ((exports_flags & ACC_SYNTHETIC) != 0)
- mods.add(Exports.Modifier.SYNTHETIC);
- 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.readModule(off, buf);
- off += 2;
- targets.add(t);
- }
- builder.exports(mods, pkg, targets);
- } else {
- builder.exports(mods, pkg);
- }
- }
- }
-
- // 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++) {
- // CONSTANT_Package_info
- String pkg = cr.readPackage(off, buf).replace('/', '.');
- off += 2;
-
- int opens_flags = cr.readUnsignedShort(off);
- off += 2;
- Set<Opens.Modifier> mods;
- if (opens_flags == 0) {
- mods = Collections.emptySet();
- } else {
- mods = new HashSet<>();
- if ((opens_flags & ACC_SYNTHETIC) != 0)
- mods.add(Opens.Modifier.SYNTHETIC);
- 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.readModule(off, buf);
- off += 2;
- targets.add(t);
- }
- builder.opens(mods, pkg, targets);
- } else {
- builder.opens(mods, pkg);
- }
- }
- }
-
- // uses_count and uses_index[uses_count]
- int uses_count = cr.readUnsignedShort(off);
- off += 2;
- if (uses_count > 0) {
- for (int i=0; i<uses_count; i++) {
- String sn = cr.readClass(off, buf).replace('/', '.');
- builder.uses(sn);
- off += 2;
- }
- }
-
- // provides_count and provides[provides_count]
- int provides_count = cr.readUnsignedShort(off);
- off += 2;
- if (provides_count > 0) {
- for (int i=0; i<provides_count; i++) {
- String service = cr.readClass(off, buf).replace('/', '.');
- off += 2;
- int with_count = cr.readUnsignedShort(off);
- off += 2;
- List<String> providers = new ArrayList<>();
- for (int j=0; j<with_count; j++) {
- String cn = cr.readClass(off, buf).replace('/', '.');
- off += 2;
- providers.add(cn);
- }
- builder.provides(service, providers);
- }
- }
-
- return new ModuleAttribute(builder.build());
- }
-
- @Override
- protected ByteVector write(ClassWriter cw,
- byte[] code,
- int len,
- int maxStack,
- int maxLocals)
- {
- assert descriptor != null;
- ByteVector attr = new ByteVector();
-
- // module_name
- String mn = descriptor.name();
- int module_name_index = cw.newModule(mn);
- attr.putShort(module_name_index);
-
- // module_flags
- Set<ModuleDescriptor.Modifier> modifiers = descriptor.modifiers();
- int module_flags = 0;
- if (modifiers.contains(ModuleDescriptor.Modifier.OPEN))
- module_flags |= ACC_OPEN;
- if (modifiers.contains(ModuleDescriptor.Modifier.SYNTHETIC))
- module_flags |= ACC_SYNTHETIC;
- if (modifiers.contains(ModuleDescriptor.Modifier.MANDATED))
- module_flags |= ACC_MANDATED;
- attr.putShort(module_flags);
-
- // module_version
- String vs = descriptor.rawVersion().orElse(null);
- if (vs == null) {
- attr.putShort(0);
- } else {
- int module_version_index = cw.newUTF8(vs);
- attr.putShort(module_version_index);
- }
-
- // requires_count
- attr.putShort(descriptor.requires().size());
-
- // requires[requires_count]
- 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;
- vs = r.rawCompiledVersion().orElse(null);
- if (vs == null) {
- requires_version_index = 0;
- } else {
- requires_version_index = cw.newUTF8(vs);
- }
- 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.newPackage(pkg));
-
- int exports_flags = 0;
- if (e.modifiers().contains(Exports.Modifier.SYNTHETIC))
- exports_flags |= ACC_SYNTHETIC;
- if (e.modifiers().contains(Exports.Modifier.MANDATED))
- exports_flags |= ACC_MANDATED;
- attr.putShort(exports_flags);
-
- if (e.isQualified()) {
- Set<String> ts = e.targets();
- attr.putShort(ts.size());
- 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.newPackage(pkg));
-
- int opens_flags = 0;
- if (obj.modifiers().contains(Opens.Modifier.SYNTHETIC))
- opens_flags |= ACC_SYNTHETIC;
- if (obj.modifiers().contains(Opens.Modifier.MANDATED))
- opens_flags |= ACC_MANDATED;
- attr.putShort(opens_flags);
-
- if (obj.isQualified()) {
- Set<String> ts = obj.targets();
- attr.putShort(ts.size());
- ts.forEach(target -> attr.putShort(cw.newModule(target)));
- } else {
- attr.putShort(0);
- }
- }
-
- // uses_count and uses_index[uses_count]
- if (descriptor.uses().isEmpty()) {
- attr.putShort(0);
- } else {
- attr.putShort(descriptor.uses().size());
- for (String s : descriptor.uses()) {
- String service = s.replace('.', '/');
- int index = cw.newClass(service);
- attr.putShort(index);
- }
- }
-
- // provides_count and provides[provides_count]
- if (descriptor.provides().isEmpty()) {
- attr.putShort(0);
- } else {
- attr.putShort(descriptor.provides().size());
- for (Provides p : descriptor.provides()) {
- String service = p.service().replace('.', '/');
- attr.putShort(cw.newClass(service));
- int with_count = p.providers().size();
- attr.putShort(with_count);
- for (String provider : p.providers()) {
- attr.putShort(cw.newClass(provider.replace('.', '/')));
- }
- }
- }
-
- return attr;
- }
- }
-
- /**
- * ModulePackages attribute.
- *
- * <pre> {@code
- *
- * ModulePackages_attribute {
- * // index to CONSTANT_utf8_info structure in constant pool representing
- * // the string "ModulePackages"
- * u2 attribute_name_index;
- * u4 attribute_length;
- *
- * // the number of entries in the packages table
- * u2 packages_count;
- * { // index to CONSTANT_Package_info structure with the package name
- * u2 package_index
- * } packages[package_count];
- *
- * }</pre>
- */
- public static class ModulePackagesAttribute extends Attribute {
- private final Set<String> packages;
-
- public ModulePackagesAttribute(Set<String> packages) {
- super(MODULE_PACKAGES);
- this.packages = packages;
- }
-
- public ModulePackagesAttribute() {
- this(null);
- }
-
- @Override
- protected Attribute read(ClassReader cr,
- int off,
- int len,
- char[] buf,
- int codeOff,
- Label[] labels)
- {
- // package count
- int package_count = cr.readUnsignedShort(off);
- off += 2;
-
- // packages
- Set<String> packages = new HashSet<>();
- for (int i=0; i<package_count; i++) {
- String pkg = cr.readPackage(off, buf).replace('/', '.');
- packages.add(pkg);
- off += 2;
- }
-
- return new ModulePackagesAttribute(packages);
- }
-
- @Override
- protected ByteVector write(ClassWriter cw,
- byte[] code,
- int len,
- int maxStack,
- int maxLocals)
- {
- assert packages != null;
-
- ByteVector attr = new ByteVector();
-
- // package_count
- attr.putShort(packages.size());
-
- // packages
- packages.stream()
- .map(p -> p.replace('.', '/'))
- .forEach(p -> attr.putShort(cw.newPackage(p)));
-
- return attr;
- }
-
- }
-
- /**
- * ModuleMainClass attribute.
- *
- * <pre> {@code
- *
- * MainClass_attribute {
- * // index to CONSTANT_utf8_info structure in constant pool representing
- * // the string "ModuleMainClass"
- * u2 attribute_name_index;
- * u4 attribute_length;
- *
- * // index to CONSTANT_Class_info structure with the main class name
- * u2 main_class_index;
- * }
- *
- * } </pre>
- */
- public static class ModuleMainClassAttribute extends Attribute {
- private final String mainClass;
-
- public ModuleMainClassAttribute(String mainClass) {
- super(MODULE_MAIN_CLASS);
- this.mainClass = mainClass;
- }
-
- public ModuleMainClassAttribute() {
- this(null);
- }
-
- @Override
- protected Attribute read(ClassReader cr,
- int off,
- int len,
- char[] buf,
- int codeOff,
- Label[] labels)
- {
- String value = cr.readClass(off, buf).replace('/', '.');
- return new ModuleMainClassAttribute(value);
- }
-
- @Override
- protected ByteVector write(ClassWriter cw,
- byte[] code,
- int len,
- int maxStack,
- int maxLocals)
- {
- ByteVector attr = new ByteVector();
- int index = cw.newClass(mainClass.replace('.', '/'));
- attr.putShort(index);
- return attr;
- }
- }
-
- /**
- * ModuleTarget attribute.
- *
- * <pre> {@code
- *
- * TargetPlatform_attribute {
- * // index to CONSTANT_utf8_info structure in constant pool representing
- * // the string "ModuleTarget"
- * u2 attribute_name_index;
- * u4 attribute_length;
- *
- * // index to CONSTANT_utf8_info structure with the target platform
- * u2 target_platform_index;
- * }
- *
- * } </pre>
- */
- public static class ModuleTargetAttribute extends Attribute {
- private final String targetPlatform;
-
- public ModuleTargetAttribute(String targetPlatform) {
- super(MODULE_TARGET);
- this.targetPlatform = targetPlatform;
- }
-
- public ModuleTargetAttribute() {
- this(null);
- }
-
- public String targetPlatform() {
- return targetPlatform;
- }
-
- @Override
- protected Attribute read(ClassReader cr,
- int off,
- int len,
- char[] buf,
- int codeOff,
- Label[] labels)
- {
-
- String targetPlatform = null;
-
- int target_platform_index = cr.readUnsignedShort(off);
- if (target_platform_index != 0)
- targetPlatform = cr.readUTF8(off, buf);
- off += 2;
-
- return new ModuleTargetAttribute(targetPlatform);
- }
-
- @Override
- protected ByteVector write(ClassWriter cw,
- byte[] code,
- int len,
- int maxStack,
- int maxLocals)
- {
- ByteVector attr = new ByteVector();
-
- int target_platform_index = 0;
- if (targetPlatform != null && targetPlatform.length() > 0)
- target_platform_index = cw.newUTF8(targetPlatform);
- attr.putShort(target_platform_index);
-
- return attr;
- }
- }
-
- /**
- * ModuleHashes attribute.
- *
- * <pre> {@code
- *
- * ModuleHashes_attribute {
- * // index to CONSTANT_utf8_info structure in constant pool representing
- * // the string "ModuleHashes"
- * u2 attribute_name_index;
- * u4 attribute_length;
- *
- * // 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 (index to CONSTANT_Module_info structure)
- * u2 hash_length;
- * u1 hash[hash_length];
- * } hashes[hashes_count];
- *
- * } </pre>
- */
- static class ModuleHashesAttribute extends Attribute {
- private final ModuleHashes hashes;
-
- ModuleHashesAttribute(ModuleHashes hashes) {
- super(MODULE_HASHES);
- this.hashes = hashes;
- }
-
- ModuleHashesAttribute() {
- this(null);
- }
-
- @Override
- protected Attribute read(ClassReader cr,
- int off,
- int len,
- char[] buf,
- int codeOff,
- Label[] labels)
- {
- String algorithm = cr.readUTF8(off, buf);
- off += 2;
-
- 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.readModule(off, buf);
- off += 2;
-
- int hash_length = cr.readUnsignedShort(off);
- off += 2;
- byte[] hash = new byte[hash_length];
- for (int j=0; j<hash_length; j++) {
- hash[j] = (byte) (0xff & cr.readByte(off+j));
- }
- off += hash_length;
-
- map.put(mn, hash);
- }
-
- ModuleHashes hashes = new ModuleHashes(algorithm, map);
-
- return new ModuleHashesAttribute(hashes);
- }
-
- @Override
- protected ByteVector write(ClassWriter cw,
- byte[] code,
- int len,
- int maxStack,
- int maxLocals)
- {
- ByteVector attr = new ByteVector();
-
- int index = cw.newUTF8(hashes.algorithm());
- attr.putShort(index);
-
- Set<String> names = hashes.names();
- attr.putShort(names.size());
-
- for (String mn : names) {
- byte[] hash = hashes.hashFor(mn);
- assert hash != null;
- attr.putShort(cw.newModule(mn));
-
- attr.putShort(hash.length);
- for (byte b: hash) {
- attr.putByte(b);
- }
- }
-
- 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;
- }
- }
-}
--- a/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java Thu Nov 02 13:18:23 2017 -0700
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java Thu Nov 02 13:20:21 2017 -0700
@@ -31,18 +31,18 @@
import java.lang.module.ModuleDescriptor.Version;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
-
-import static jdk.internal.module.ClassFileAttributes.*;
+import jdk.internal.org.objectweb.asm.commons.ModuleHashesAttribute;
+import jdk.internal.org.objectweb.asm.commons.ModuleResolutionAttribute;
+import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute;
/**
* Utility class to extend a module-info.class with additional attributes.
@@ -133,43 +133,6 @@
}
/**
- * A ClassVisitor that supports adding class file attributes. If an
- * attribute already exists then the first occurrence of the attribute
- * is replaced.
- */
- private static class AttributeAddingClassVisitor extends ClassVisitor {
- private Map<String, Attribute> attrs = new HashMap<>();
-
- AttributeAddingClassVisitor(int api, ClassVisitor cv) {
- super(api, cv);
- }
-
- void addAttribute(Attribute attr) {
- attrs.put(attr.type, attr);
- }
-
- @Override
- public void visitAttribute(Attribute attr) {
- String name = attr.type;
- Attribute replacement = attrs.get(name);
- if (replacement != null) {
- attr = replacement;
- attrs.remove(name);
- }
- super.visitAttribute(attr);
- }
-
- /**
- * Adds any remaining attributes that weren't replaced to the
- * class file.
- */
- void finish() {
- attrs.values().forEach(a -> super.visitAttribute(a));
- attrs.clear();
- }
- }
-
- /**
* Outputs the modified module-info.class to the given output stream.
* Once this method has been called then the Extender object should
* be discarded.
@@ -185,38 +148,86 @@
* be discarded.
*/
public byte[] toByteArray() throws IOException {
- ClassWriter cw
- = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
-
- AttributeAddingClassVisitor cv
- = new AttributeAddingClassVisitor(Opcodes.ASM5, cw);
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+ + ClassWriter.COMPUTE_FRAMES);
ClassReader cr = new ClassReader(in);
- if (packages != null)
- cv.addAttribute(new ModulePackagesAttribute(packages));
- if (mainClass != null)
- cv.addAttribute(new ModuleMainClassAttribute(mainClass));
- if (targetPlatform != null)
- cv.addAttribute(new ModuleTargetAttribute(targetPlatform));
- if (hashes != null)
- cv.addAttribute(new ModuleHashesAttribute(hashes));
- if (moduleResolution != null)
- cv.addAttribute(new ModuleResolutionAttribute(moduleResolution.value()));
+ ClassVisitor cv = new ClassVisitor(Opcodes.ASM6, cw) {
+ @Override
+ public ModuleVisitor visitModule(String name, int flags, String version) {
+ Version v = ModuleInfoExtender.this.version;
+ String vs = (v != null) ? v.toString() : version;
+ ModuleVisitor mv = super.visitModule(name, flags, vs);
+
+ // ModuleMainClass attribute
+ if (mainClass != null) {
+ mv.visitMainClass(mainClass.replace('.', '/'));
+ }
+
+ // ModulePackages attribute
+ if (packages != null) {
+ packages.forEach(pn -> mv.visitPackage(pn.replace('.', '/')));
+ }
+
+ return new ModuleVisitor(Opcodes.ASM6, mv) {
+ public void visitMainClass(String existingMainClass) {
+ // skip main class if there is a new value
+ if (mainClass == null) {
+ super.visitMainClass(existingMainClass);
+ }
+ }
+ public void visitPackage(String existingPackage) {
+ // skip packages if there is a new set of packages
+ if (packages == null) {
+ super.visitPackage(existingPackage);
+ }
+ }
+ };
+ }
+ @Override
+ public void visitAttribute(Attribute attr) {
+ String name = attr.type;
+ // drop existing attributes if there are replacements
+ if (name.equals(ClassFileConstants.MODULE_TARGET)
+ && targetPlatform != null)
+ return;
+ if (name.equals(ClassFileConstants.MODULE_RESOLUTION)
+ && moduleResolution != null)
+ return;
+ if (name.equals(ClassFileConstants.MODULE_HASHES)
+ && hashes != null)
+ return;
+
+ super.visitAttribute(attr);
+
+ }
+ };
List<Attribute> attrs = new ArrayList<>();
-
- // prototypes of attributes that should be parsed
- attrs.add(new ModuleAttribute(version));
- attrs.add(new ModulePackagesAttribute());
- attrs.add(new ModuleMainClassAttribute());
attrs.add(new ModuleTargetAttribute());
+ attrs.add(new ModuleResolutionAttribute());
attrs.add(new ModuleHashesAttribute());
-
cr.accept(cv, attrs.toArray(new Attribute[0]), 0);
- // add any attributes that didn't replace previous attributes
- cv.finish();
+ // add ModuleTarget, ModuleResolution and ModuleHashes attributes
+ if (targetPlatform != null) {
+ cw.visitAttribute(new ModuleTargetAttribute(targetPlatform));
+ }
+ if (moduleResolution != null) {
+ int flags = moduleResolution.value();
+ cw.visitAttribute(new ModuleResolutionAttribute(flags));
+ }
+ if (hashes != null) {
+ String algorithm = hashes.algorithm();
+ List<String> names = new ArrayList<>();
+ List<byte[]> values = new ArrayList<>();
+ for (String name : hashes.names()) {
+ names.add(name);
+ values.add(hashes.hashFor(name));
+ }
+ cw.visitAttribute(new ModuleHashesAttribute(algorithm, names, values));
+ }
return cw.toByteArray();
}
--- a/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java Thu Nov 02 13:18:23 2017 -0700
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java Thu Nov 02 13:20:21 2017 -0700
@@ -28,13 +28,14 @@
import java.io.OutputStream;
import java.lang.module.ModuleDescriptor;
import java.nio.ByteBuffer;
+import java.util.Map;
import java.util.stream.Stream;
import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
-
-import static jdk.internal.module.ClassFileAttributes.*;
-import static jdk.internal.module.ClassFileConstants.ACC_MODULE;
+import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
/**
* Utility class to write a ModuleDescriptor as a module-info.class.
@@ -42,6 +43,35 @@
public final class ModuleInfoWriter {
+ private static final Map<ModuleDescriptor.Modifier, Integer>
+ MODULE_MODS_TO_FLAGS = Map.of(
+ ModuleDescriptor.Modifier.OPEN, ACC_OPEN,
+ ModuleDescriptor.Modifier.SYNTHETIC, ACC_SYNTHETIC,
+ ModuleDescriptor.Modifier.MANDATED, ACC_MANDATED
+ );
+
+ private static final Map<ModuleDescriptor.Requires.Modifier, Integer>
+ REQUIRES_MODS_TO_FLAGS = Map.of(
+ ModuleDescriptor.Requires.Modifier.TRANSITIVE, ACC_TRANSITIVE,
+ ModuleDescriptor.Requires.Modifier.STATIC, ACC_STATIC_PHASE,
+ ModuleDescriptor.Requires.Modifier.SYNTHETIC, ACC_SYNTHETIC,
+ ModuleDescriptor.Requires.Modifier.MANDATED, ACC_MANDATED
+ );
+
+ private static final Map<ModuleDescriptor.Exports.Modifier, Integer>
+ EXPORTS_MODS_TO_FLAGS = Map.of(
+ ModuleDescriptor.Exports.Modifier.SYNTHETIC, ACC_SYNTHETIC,
+ ModuleDescriptor.Exports.Modifier.MANDATED, ACC_MANDATED
+ );
+
+ private static final Map<ModuleDescriptor.Opens.Modifier, Integer>
+ OPENS_MODS_TO_FLAGS = Map.of(
+ ModuleDescriptor.Opens.Modifier.SYNTHETIC, ACC_SYNTHETIC,
+ ModuleDescriptor.Opens.Modifier.MANDATED, ACC_MANDATED
+ );
+
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
private ModuleInfoWriter() { }
/**
@@ -50,24 +80,75 @@
*/
private static byte[] toModuleInfo(ModuleDescriptor md, ModuleTarget target) {
ClassWriter cw = new ClassWriter(0);
- cw.visit(Opcodes.V1_9, ACC_MODULE, "module-info", null, null, null);
- cw.visitAttribute(new ModuleAttribute(md));
+ cw.visit(Opcodes.V9, ACC_MODULE, "module-info", null, null, null);
+
+ int moduleFlags = md.modifiers().stream()
+ .map(MODULE_MODS_TO_FLAGS::get)
+ .reduce(0, (x, y) -> (x | y));
+ String vs = md.rawVersion().orElse(null);
+ ModuleVisitor mv = cw.visitModule(md.name(), moduleFlags, vs);
+
+ // requires
+ for (ModuleDescriptor.Requires r : md.requires()) {
+ int flags = r.modifiers().stream()
+ .map(REQUIRES_MODS_TO_FLAGS::get)
+ .reduce(0, (x, y) -> (x | y));
+ vs = r.rawCompiledVersion().orElse(null);
+ mv.visitRequire(r.name(), flags, vs);
+ }
- // for tests: write the ModulePackages attribute when there are packages
- // that aren't exported or open
+ // exports
+ for (ModuleDescriptor.Exports e : md.exports()) {
+ int flags = e.modifiers().stream()
+ .map(EXPORTS_MODS_TO_FLAGS::get)
+ .reduce(0, (x, y) -> (x | y));
+ String[] targets = e.targets().toArray(EMPTY_STRING_ARRAY);
+ mv.visitExport(e.source().replace('.', '/'), flags, targets);
+ }
+
+ // opens
+ for (ModuleDescriptor.Opens opens : md.opens()) {
+ int flags = opens.modifiers().stream()
+ .map(OPENS_MODS_TO_FLAGS::get)
+ .reduce(0, (x, y) -> (x | y));
+ String[] targets = opens.targets().toArray(EMPTY_STRING_ARRAY);
+ mv.visitOpen(opens.source().replace('.', '/'), flags, targets);
+ }
+
+ // uses
+ md.uses().stream().map(sn -> sn.replace('.', '/')).forEach(mv::visitUse);
+
+ // provides
+ for (ModuleDescriptor.Provides p : md.provides()) {
+ mv.visitProvide(p.service().replace('.', '/'),
+ p.providers()
+ .stream()
+ .map(pn -> pn.replace('.', '/'))
+ .toArray(String[]::new));
+ }
+
+ // add the ModulePackages attribute when there are packages that aren't
+ // exported or open
Stream<String> exported = md.exports().stream()
.map(ModuleDescriptor.Exports::source);
Stream<String> open = md.opens().stream()
.map(ModuleDescriptor.Opens::source);
long exportedOrOpen = Stream.concat(exported, open).distinct().count();
- if (md.packages().size() > exportedOrOpen)
- cw.visitAttribute(new ModulePackagesAttribute(md.packages()));
+ if (md.packages().size() > exportedOrOpen) {
+ md.packages().stream()
+ .map(pn -> pn.replace('.', '/'))
+ .forEach(mv::visitPackage);
+ }
- // write ModuleMainClass if the module has a main class
- md.mainClass().ifPresent(mc -> cw.visitAttribute(new ModuleMainClassAttribute(mc)));
+ // ModuleMainClass attribute
+ md.mainClass()
+ .map(mc -> mc.replace('.', '/'))
+ .ifPresent(mv::visitMainClass);
- // write ModuleTarget if there is a target platform
- if (target != null) {
+ mv.visitEnd();
+
+ // write ModuleTarget attribute if there is a target platform
+ if (target != null && target.targetPlatform().length() > 0) {
cw.visitAttribute(new ModuleTargetAttribute(target.targetPlatform()));
}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java Thu Nov 02 13:18:23 2017 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java Thu Nov 02 13:20:21 2017 -0700
@@ -58,8 +58,6 @@
import java.util.stream.Collectors;
import jdk.internal.module.Checks;
-import jdk.internal.module.ClassFileAttributes;
-import jdk.internal.module.ClassFileConstants;
import jdk.internal.module.DefaultRoots;
import jdk.internal.module.IllegalAccessMaps;
import jdk.internal.module.ModuleHashes;
@@ -68,13 +66,13 @@
import jdk.internal.module.ModuleReferenceImpl;
import jdk.internal.module.ModuleResolution;
import jdk.internal.module.ModuleTarget;
-import jdk.internal.org.objectweb.asm.Attribute;
+
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.ModuleVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
-
import static jdk.internal.org.objectweb.asm.Opcodes.*;
import jdk.tools.jlink.internal.ModuleSorter;
@@ -435,24 +433,25 @@
}
boolean hasModulePackages() throws IOException {
- Set<String> attrTypes = new HashSet<>();
- ClassVisitor cv = new ClassVisitor(Opcodes.ASM5) {
+ Set<String> packages = new HashSet<>();
+ ClassVisitor cv = new ClassVisitor(Opcodes.ASM6) {
@Override
- public void visitAttribute(Attribute attr) {
- attrTypes.add(attr.type);
+ public ModuleVisitor visitModule(String name,
+ int flags,
+ String version) {
+ return new ModuleVisitor(Opcodes.ASM6) {
+ public void visitPackage(String pn) {
+ packages.add(pn);
+ }
+ };
}
};
- // prototype of attributes that should be parsed
- Attribute[] attrs = new Attribute[] {
- new ClassFileAttributes.ModulePackagesAttribute()
- };
-
try (InputStream in = getInputStream()) {
// parse module-info.class
ClassReader cr = new ClassReader(in);
- cr.accept(cv, attrs, 0);
- return attrTypes.contains(ClassFileConstants.MODULE_PACKAGES);
+ cr.accept(cv, 0);
+ return packages.size() > 0;
}
}