From 714b5f036fc70d8d1d4d3ec8777fe95cffc0fe5b Mon Sep 17 00:00:00 2001 From: Adam Sotona Date: Wed, 15 Mar 2023 07:09:55 +0000 Subject: [PATCH] 8294962: Convert java.base/jdk.internal.module package to use the Classfile API to modify and write module-info.class Reviewed-by: alanb, mchung --- .../jdk/internal/classfile/Classfile.java | 44 +---- .../classfile/attribute/ModuleAttribute.java | 13 ++ .../impl/ModuleAttributeBuilderImpl.java | 8 +- .../internal/module/ModuleInfoExtender.java | 143 +++++--------- .../jdk/internal/module/ModuleInfoWriter.java | 185 +++++++++--------- .../lang/module/ModuleDescriptorTest.java | 20 +- test/jdk/jdk/classfile/ModuleBuilderTest.java | 4 +- .../classfile/examples/ModuleExamples.java | 2 +- 8 files changed, 185 insertions(+), 234 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/classfile/Classfile.java b/src/java.base/share/classes/jdk/internal/classfile/Classfile.java index a4bd38adb25..5c8d7abaa35 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/Classfile.java +++ b/src/java.base/share/classes/jdk/internal/classfile/Classfile.java @@ -250,44 +250,20 @@ public class Classfile { * @return the classfile bytes */ public static byte[] buildModule(ModuleAttribute moduleAttribute) { - return buildModule(moduleAttribute, List.of(), clb -> {}); + return buildModule(moduleAttribute, clb -> {}); } /** * Build a module descriptor into a byte array. * @param moduleAttribute the {@code Module} attribute - * @param packages additional module packages - * @return the classfile bytes - */ - public static byte[] buildModule(ModuleAttribute moduleAttribute, - List packages) { - return buildModule(moduleAttribute, packages, clb -> {}); - } - - /** - * Build a module descriptor into a byte array. - * @param moduleAttribute the {@code Module} attribute - * @param packages additional module packages * @param handler a handler that receives a {@link ClassBuilder} * @return the classfile bytes */ public static byte[] buildModule(ModuleAttribute moduleAttribute, - List packages, Consumer handler) { return build(ClassDesc.of("module-info"), clb -> { clb.withFlags(AccessFlag.MODULE); clb.with(moduleAttribute); - if (!packages.isEmpty()) { - var cp = clb.constantPool(); - var allPackages = new LinkedHashSet(); - for (var exp : moduleAttribute.exports()) allPackages.add(AbstractPoolEntry.maybeClone(cp, exp.exportedPackage())); - for (var opn : moduleAttribute.opens()) allPackages.add(AbstractPoolEntry.maybeClone(cp, opn.openedPackage())); - boolean emitMPA = false; - for (var p : packages) - emitMPA |= allPackages.add(cp.packageEntry(p)); - if(emitMPA) - clb.with(new UnboundAttribute.UnboundModulePackagesAttribute(allPackages)); - } handler.accept(clb); }); } @@ -299,33 +275,19 @@ public class Classfile { */ public static void buildModuleTo(Path path, ModuleAttribute moduleAttribute) throws IOException { - buildModuleTo(path, moduleAttribute, List.of(), clb -> {}); + buildModuleTo(path, moduleAttribute, clb -> {}); } /** * Build a module descriptor into a file. * @param path the file to write * @param moduleAttribute the {@code Module} attribute - * @param packages additional module packages - */ - public static void buildModuleTo(Path path, - ModuleAttribute moduleAttribute, - List packages) throws IOException { - buildModuleTo(path, moduleAttribute, packages, clb -> {}); - } - - /** - * Build a module descriptor into a file. - * @param path the file to write - * @param moduleAttribute the {@code Module} attribute - * @param packages additional module packages * @param handler a handler that receives a {@link ClassBuilder} */ public static void buildModuleTo(Path path, ModuleAttribute moduleAttribute, - List packages, Consumer handler) throws IOException { - Files.write(path, buildModule(moduleAttribute, packages, handler)); + Files.write(path, buildModule(moduleAttribute, handler)); } public static final int MAGIC_NUMBER = 0xCAFEBABE; diff --git a/src/java.base/share/classes/jdk/internal/classfile/attribute/ModuleAttribute.java b/src/java.base/share/classes/jdk/internal/classfile/attribute/ModuleAttribute.java index 6511134b125..71fb892005a 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/attribute/ModuleAttribute.java +++ b/src/java.base/share/classes/jdk/internal/classfile/attribute/ModuleAttribute.java @@ -142,6 +142,19 @@ public sealed interface ModuleAttribute return mb.build(); } + /** + * {@return a {@code Module} attribute} + * + * @param moduleName the module name + * @param attrHandler a handler that receives a {@link ModuleAttributeBuilder} + */ + static ModuleAttribute of(ModuleEntry moduleName, + Consumer attrHandler) { + var mb = new ModuleAttributeBuilderImpl(moduleName); + attrHandler.accept(mb); + return mb.build(); + } + public sealed interface ModuleAttributeBuilder permits ModuleAttributeBuilderImpl { diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ModuleAttributeBuilderImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ModuleAttributeBuilderImpl.java index 057c5f9d907..cefd201af66 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ModuleAttributeBuilderImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ModuleAttributeBuilderImpl.java @@ -49,11 +49,15 @@ public final class ModuleAttributeBuilderImpl private final Set uses = new LinkedHashSet<>(); private final Set provides = new LinkedHashSet<>(); - public ModuleAttributeBuilderImpl(ModuleDesc moduleName) { - this.moduleEntry = TemporaryConstantPool.INSTANCE.moduleEntry(TemporaryConstantPool.INSTANCE.utf8Entry(moduleName.moduleName())); + public ModuleAttributeBuilderImpl(ModuleEntry moduleName) { + this.moduleEntry = moduleName; this.moduleFlags = 0; } + public ModuleAttributeBuilderImpl(ModuleDesc moduleName) { + this(TemporaryConstantPool.INSTANCE.moduleEntry(TemporaryConstantPool.INSTANCE.utf8Entry(moduleName.moduleName()))); + } + @Override public ModuleAttribute build() { return new UnboundAttribute.UnboundModuleAttribute(moduleEntry, moduleFlags, moduleVersion, diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java b/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java index 7015194169b..8b4eef0f5f3 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java @@ -28,21 +28,23 @@ package jdk.internal.module; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.lang.constant.ClassDesc; import java.lang.module.ModuleDescriptor.Version; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; +import jdk.internal.classfile.Classfile; +import jdk.internal.classfile.ClassTransform; +import jdk.internal.classfile.attribute.ModuleAttribute; +import jdk.internal.classfile.attribute.ModuleHashInfo; +import jdk.internal.classfile.attribute.ModuleHashesAttribute; +import jdk.internal.classfile.attribute.ModuleMainClassAttribute; +import jdk.internal.classfile.attribute.ModulePackagesAttribute; +import jdk.internal.classfile.attribute.ModuleResolutionAttribute; +import jdk.internal.classfile.attribute.ModuleTargetAttribute; +import jdk.internal.classfile.java.lang.constant.ModuleDesc; +import jdk.internal.classfile.java.lang.constant.PackageDesc; -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 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. @@ -148,90 +150,53 @@ public final class ModuleInfoExtender { * be discarded. */ public byte[] toByteArray() throws IOException { - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS - + ClassWriter.COMPUTE_FRAMES); - - ClassReader cr = new ClassReader(in); - - ClassVisitor cv = new ClassVisitor(Opcodes.ASM7, 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.stream() - .sorted() - .forEach(pn -> mv.visitPackage(pn.replace('.', '/'))); - } - - return new ModuleVisitor(Opcodes.ASM7, 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); - } - } - }; + var cm = Classfile.parse(in.readAllBytes()); + Version v = ModuleInfoExtender.this.version; + return cm.transform(ClassTransform.endHandler(clb -> { + // ModuleMainClass attribute + if (mainClass != null) { + clb.with(ModuleMainClassAttribute.of(ClassDesc.of(mainClass))); } - @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); + // ModulePackages attribute + if (packages != null) { + List packageNames = packages.stream() + .sorted() + .map(PackageDesc::of) + .toList(); + clb.with(ModulePackagesAttribute.ofNames(packageNames)); } - }; - List attrs = new ArrayList<>(); - attrs.add(new ModuleTargetAttribute()); - attrs.add(new ModuleResolutionAttribute()); - attrs.add(new ModuleHashesAttribute()); - cr.accept(cv, attrs.toArray(new Attribute[0]), 0); - - // 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 names = new ArrayList<>(); - List values = new ArrayList<>(); - for (String name : hashes.names()) { - names.add(name); - values.add(hashes.hashFor(name)); + // ModuleTarget, ModuleResolution and ModuleHashes attributes + if (targetPlatform != null) { + clb.with(ModuleTargetAttribute.of(targetPlatform)); } - cw.visitAttribute(new ModuleHashesAttribute(algorithm, names, values)); - } - - return cw.toByteArray(); + if (moduleResolution != null) { + clb.with(ModuleResolutionAttribute.of(moduleResolution.value())); + } + if (hashes != null) { + clb.with(ModuleHashesAttribute.of( + hashes.algorithm(), + hashes.hashes().entrySet().stream().map(he -> + ModuleHashInfo.of(ModuleDesc.of( + he.getKey()), + he.getValue())).toList())); + } + }).andThen((clb, cle) -> { + if (v != null && cle instanceof ModuleAttribute ma) { + clb.with(ModuleAttribute.of( + ma.moduleName(), + ma.moduleFlagsMask(), + clb.constantPool().utf8Entry(v.toString()), + ma.requires(), + ma.exports(), + ma.opens(), + ma.uses(), + ma.provides())); + } else { + clb.accept(cle); + } + })); } /** diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java b/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java index 1a751423358..1530fa9221c 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java @@ -26,17 +26,22 @@ package jdk.internal.module; import java.io.IOException; import java.io.OutputStream; +import java.lang.constant.ClassDesc; import java.lang.module.ModuleDescriptor; +import java.lang.reflect.AccessFlag; 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 jdk.internal.org.objectweb.asm.commons.ModuleResolutionAttribute; -import jdk.internal.org.objectweb.asm.commons.ModuleTargetAttribute; -import static jdk.internal.org.objectweb.asm.Opcodes.*; +import jdk.internal.classfile.Classfile; +import jdk.internal.classfile.java.lang.constant.PackageDesc; +import jdk.internal.classfile.attribute.ModuleAttribute; +import jdk.internal.classfile.attribute.ModuleExportInfo; +import jdk.internal.classfile.attribute.ModuleMainClassAttribute; +import jdk.internal.classfile.attribute.ModuleOpenInfo; +import jdk.internal.classfile.attribute.ModulePackagesAttribute; +import jdk.internal.classfile.attribute.ModuleResolutionAttribute; +import jdk.internal.classfile.attribute.ModuleRequireInfo; +import jdk.internal.classfile.attribute.ModuleTargetAttribute; +import jdk.internal.classfile.constantpool.ModuleEntry; /** * Utility class to write a ModuleDescriptor as a module-info.class. @@ -46,33 +51,31 @@ public final class ModuleInfoWriter { private static final Map MODULE_MODS_TO_FLAGS = Map.of( - ModuleDescriptor.Modifier.OPEN, ACC_OPEN, - ModuleDescriptor.Modifier.SYNTHETIC, ACC_SYNTHETIC, - ModuleDescriptor.Modifier.MANDATED, ACC_MANDATED + ModuleDescriptor.Modifier.OPEN, Classfile.ACC_OPEN, + ModuleDescriptor.Modifier.SYNTHETIC, Classfile.ACC_SYNTHETIC, + ModuleDescriptor.Modifier.MANDATED, Classfile.ACC_MANDATED ); private static final Map 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 + ModuleDescriptor.Requires.Modifier.TRANSITIVE, Classfile.ACC_TRANSITIVE, + ModuleDescriptor.Requires.Modifier.STATIC, Classfile.ACC_STATIC_PHASE, + ModuleDescriptor.Requires.Modifier.SYNTHETIC, Classfile.ACC_SYNTHETIC, + ModuleDescriptor.Requires.Modifier.MANDATED, Classfile.ACC_MANDATED ); private static final Map EXPORTS_MODS_TO_FLAGS = Map.of( - ModuleDescriptor.Exports.Modifier.SYNTHETIC, ACC_SYNTHETIC, - ModuleDescriptor.Exports.Modifier.MANDATED, ACC_MANDATED + ModuleDescriptor.Exports.Modifier.SYNTHETIC, Classfile.ACC_SYNTHETIC, + ModuleDescriptor.Exports.Modifier.MANDATED, Classfile.ACC_MANDATED ); private static final Map OPENS_MODS_TO_FLAGS = Map.of( - ModuleDescriptor.Opens.Modifier.SYNTHETIC, ACC_SYNTHETIC, - ModuleDescriptor.Opens.Modifier.MANDATED, ACC_MANDATED + ModuleDescriptor.Opens.Modifier.SYNTHETIC, Classfile.ACC_SYNTHETIC, + ModuleDescriptor.Opens.Modifier.MANDATED, Classfile.ACC_MANDATED ); - private static final String[] EMPTY_STRING_ARRAY = new String[0]; - private ModuleInfoWriter() { } /** @@ -82,86 +85,86 @@ public final class ModuleInfoWriter { private static byte[] toModuleInfo(ModuleDescriptor md, ModuleResolution mres, ModuleTarget target) { - ClassWriter cw = new ClassWriter(0); - cw.visit(Opcodes.V10, ACC_MODULE, "module-info", null, null, null); + //using low-level module building to avoid validation in ModuleDesc and allow invalid names + return Classfile.build(ClassDesc.of("module-info"), clb -> { + clb.withFlags(AccessFlag.MODULE); + var cp = clb.constantPool(); + clb.with(ModuleAttribute.of(cp.moduleEntry(cp.utf8Entry(md.name())), mb -> { + mb.moduleFlags(md.modifiers().stream() + .mapToInt(mm -> MODULE_MODS_TO_FLAGS.getOrDefault(mm, 0)) + .reduce(0, (x, y) -> (x | y))); - 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); + md.rawVersion().ifPresent(vs -> mb.moduleVersion(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); - } + // requires + for (ModuleDescriptor.Requires r : md.requires()) { + int flags = r.modifiers().stream() + .mapToInt(REQUIRES_MODS_TO_FLAGS::get) + .reduce(0, (x, y) -> (x | y)); + mb.requires(ModuleRequireInfo.of( + cp.moduleEntry(cp.utf8Entry(r.name())), + flags, + r.rawCompiledVersion().map(cp::utf8Entry).orElse(null))); + } - // 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); - } + // exports + for (ModuleDescriptor.Exports e : md.exports()) { + int flags = e.modifiers().stream() + .mapToInt(EXPORTS_MODS_TO_FLAGS::get) + .reduce(0, (x, y) -> (x | y)); + var targets = e.targets().stream().map(mn -> cp.moduleEntry(cp.utf8Entry(mn))) + .toArray(ModuleEntry[]::new); + mb.exports(ModuleExportInfo.of( + cp.packageEntry(cp.utf8Entry(e.source())), + 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); - } + // opens + for (ModuleDescriptor.Opens opens : md.opens()) { + int flags = opens.modifiers().stream() + .mapToInt(OPENS_MODS_TO_FLAGS::get) + .reduce(0, (x, y) -> (x | y)); + var targets = opens.targets().stream().map(mn -> cp.moduleEntry(cp.utf8Entry(mn))) + .toArray(ModuleEntry[]::new); + mb.opens(ModuleOpenInfo.of( + cp.packageEntry(cp.utf8Entry(opens.source())), + flags, + targets)); + } - // uses - md.uses().stream().map(sn -> sn.replace('.', '/')).forEach(mv::visitUse); + // uses + md.uses().stream().map(ClassDesc::of).forEach(mb::uses); - // provides - for (ModuleDescriptor.Provides p : md.provides()) { - mv.visitProvide(p.service().replace('.', '/'), - p.providers() - .stream() - .map(pn -> pn.replace('.', '/')) - .toArray(String[]::new)); - } + // provides + for (ModuleDescriptor.Provides p : md.provides()) { + mb.provides(ClassDesc.of(p.service()), + p.providers().stream() + .map(ClassDesc::of) + .toArray(ClassDesc[]::new)); + } + })); - // add the ModulePackages attribute when there are packages that aren't - // exported or open - Stream exported = md.exports().stream() - .map(ModuleDescriptor.Exports::source); - Stream open = md.opens().stream() - .map(ModuleDescriptor.Opens::source); - long exportedOrOpen = Stream.concat(exported, open).distinct().count(); - if (md.packages().size() > exportedOrOpen) { - md.packages().stream() - .map(pn -> pn.replace('.', '/')) - .forEach(mv::visitPackage); - } + // packages + var packages = md.packages().stream().sorted().map(PackageDesc::of).toList(); + if (!packages.isEmpty()) { + clb.with(ModulePackagesAttribute.ofNames(packages)); + } - // ModuleMainClass attribute - md.mainClass() - .map(mc -> mc.replace('.', '/')) - .ifPresent(mv::visitMainClass); + // ModuleMainClass attribute + md.mainClass().ifPresent(mc -> + clb.with(ModuleMainClassAttribute.of(ClassDesc.of(mc)))); - mv.visitEnd(); + // write ModuleResolution attribute if specified + if (mres != null) { + clb.with(ModuleResolutionAttribute.of(mres.value())); + } - // write ModuleResolution attribute if specified - if (mres != null) { - cw.visitAttribute(new ModuleResolutionAttribute(mres.value())); - } - - // write ModuleTarget attribute if there is a target platform - if (target != null && target.targetPlatform().length() > 0) { - cw.visitAttribute(new ModuleTargetAttribute(target.targetPlatform())); - } - - cw.visitEnd(); - return cw.toByteArray(); + // write ModuleTarget attribute if there is a target platform + if (target != null && !target.targetPlatform().isEmpty()) { + clb.with(ModuleTargetAttribute.of(target.targetPlatform())); + } + }); } /** diff --git a/test/jdk/java/lang/module/ModuleDescriptorTest.java b/test/jdk/java/lang/module/ModuleDescriptorTest.java index 02c5d473d96..e495443a83e 100644 --- a/test/jdk/java/lang/module/ModuleDescriptorTest.java +++ b/test/jdk/java/lang/module/ModuleDescriptorTest.java @@ -26,6 +26,9 @@ * @bug 8142968 8158456 8298875 * @modules java.base/jdk.internal.access * java.base/jdk.internal.module + * java.base/jdk.internal.classfile + * java.base/jdk.internal.classfile.attribute + * java.base/jdk.internal.classfile.java.lang.constant * @run testng ModuleDescriptorTest * @summary Basic test for java.lang.module.ModuleDescriptor and its builder */ @@ -57,6 +60,10 @@ import static java.lang.module.ModuleDescriptor.Requires.Modifier.*; import jdk.internal.access.JavaLangModuleAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.classfile.Classfile; +import jdk.internal.classfile.attribute.ModuleAttribute; +import jdk.internal.classfile.java.lang.constant.PackageDesc; +import jdk.internal.classfile.java.lang.constant.ModuleDesc; import jdk.internal.module.ModuleInfoWriter; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -1362,14 +1369,11 @@ public class ModuleDescriptorTest { * complete set of packages. */ public void testReadsWithBadPackageFinder() throws Exception { - ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo") - .requires("java.base") - .exports("p") - .build(); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ModuleInfoWriter.write(descriptor, baos); - ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray()); + ByteBuffer bb = ByteBuffer.wrap(Classfile.buildModule( + ModuleAttribute.of( + ModuleDesc.of("foo"), + mb -> mb.requires(ModuleDesc.of("java.base"), 0, null) + .exports(PackageDesc.of("p"), 0)))); // package finder returns a set that doesn't include p assertThrows(InvalidModuleDescriptorException.class, diff --git a/test/jdk/jdk/classfile/ModuleBuilderTest.java b/test/jdk/jdk/classfile/ModuleBuilderTest.java index 015c8c49430..4b3e6a285ea 100644 --- a/test/jdk/jdk/classfile/ModuleBuilderTest.java +++ b/test/jdk/jdk/classfile/ModuleBuilderTest.java @@ -85,8 +85,8 @@ class ModuleBuilderTest { .uses(ClassDesc.of("another.Service")) .provides(ClassDesc.of("some.nice.Feature"), ClassDesc.of("impl"), ClassDesc.of("another.impl"))), - List.of(PackageDesc.of("foo.bar.baz"), PackageDesc.of("quux"), PackageDesc.of("foo.bar.baz"), PackageDesc.of("quux")), clb -> clb.with(ModuleMainClassAttribute.of(ClassDesc.of("main.Class"))) + .with(ModulePackagesAttribute.ofNames(PackageDesc.of("foo.bar.baz"), PackageDesc.of("quux"))) .with(ModuleMainClassAttribute.of(ClassDesc.of("overwritten.main.Class")))); moduleModel = Classfile.parse(modInfo); attr = ((ModuleAttribute) moduleModel.attributes().stream() @@ -182,7 +182,7 @@ class ModuleBuilderTest { @Test void verifyPackages() { ModulePackagesAttribute a = moduleModel.findAttribute(Attributes.MODULE_PACKAGES).orElseThrow(); - assertEquals(a.packages().stream().map(pe -> pe.asSymbol().packageName()).toList(), List.of("0", "1", "2", "3", "4", "o0", "o1", "o2", "foo.bar.baz", "quux")); + assertEquals(a.packages().stream().map(pe -> pe.asSymbol().packageName()).toList(), List.of("foo.bar.baz", "quux")); } @Test diff --git a/test/jdk/jdk/classfile/examples/ModuleExamples.java b/test/jdk/jdk/classfile/examples/ModuleExamples.java index 0ef4f35b7e9..5ffdbb51bfa 100644 --- a/test/jdk/jdk/classfile/examples/ModuleExamples.java +++ b/test/jdk/jdk/classfile/examples/ModuleExamples.java @@ -78,7 +78,7 @@ public class ModuleExamples { }); // Build it - byte[] moduleInfo = Classfile.buildModule(ModuleAttribute.of(moduleName, handler), List.of(), clb -> { + byte[] moduleInfo = Classfile.buildModule(ModuleAttribute.of(moduleName, handler), clb -> { // Add an annotation to the module clb.with(RuntimeVisibleAnnotationsAttribute.of(Annotation.of(ClassDesc.ofDescriptor("Ljava/lang/Deprecated;"),