Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (101)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (309)
Collections:
Other Resources:
JDK 11 jdk.jlink.jmod - JLink Tool
JDK 11 jdk.jlink.jmod is the JMOD file for JDK 11 JLink tool, which can be invoked by the "jlink" command.
JDK 11 JLink tool compiled class files are stored in \fyicenter\jdk-11.0.1\jmods\jdk.jlink.jmod.
JDK 11 JLink tool compiled class files are also linked and stored in the \fyicenter\jdk-11.0.1\lib\modules JImage file.
JDK 11 JLink tool source code files are stored in \fyicenter\jdk-11.0.1\lib\src.zip\jdk.jlink.
You can click and view the content of each source code file in the list below.
✍: FYIcenter
⏎ jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
/* * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * * * * * * * * * * * * * * * * * * * * */ package jdk.tools.jlink.internal.plugins; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor.Exports; import java.lang.module.ModuleDescriptor.Opens; import java.lang.module.ModuleDescriptor.Provides; import java.lang.module.ModuleDescriptor.Requires; import java.lang.module.ModuleDescriptor.Version; import java.lang.module.ModuleFinder; import java.lang.module.ModuleReader; import java.lang.module.ModuleReference; import java.lang.module.ResolvedModule; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.TreeSet; import java.util.function.IntSupplier; import java.util.function.Supplier; import java.util.stream.Collectors; import jdk.internal.module.Checks; import jdk.internal.module.DefaultRoots; import jdk.internal.module.IllegalAccessMaps; import jdk.internal.module.ModuleHashes; import jdk.internal.module.ModuleInfo.Attributes; import jdk.internal.module.ModuleInfoExtender; import jdk.internal.module.ModuleReferenceImpl; import jdk.internal.module.ModuleResolution; import jdk.internal.module.ModuleTarget; 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; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.plugin.PluginException; import jdk.tools.jlink.plugin.ResourcePool; import jdk.tools.jlink.plugin.ResourcePoolBuilder; import jdk.tools.jlink.plugin.ResourcePoolEntry; /** * Jlink plugin to reconstitute module descriptors and other attributes for system * modules. The plugin generates implementations of SystemModules to avoid parsing * module-info.class files at startup. It also generates SystemModulesMap to return * the SystemModules implementation for a specific initial module. * * As a side effect, the plugin adds the ModulePackages class file attribute to the * module-info.class files that don't have the attribute. * * @see jdk.internal.module.SystemModuleFinders * @see jdk.internal.module.SystemModules */ public final class SystemModulesPlugin implements Plugin { private static final String NAME = "system-modules"; private static final String DESCRIPTION = PluginsResourceBundle.getDescription(NAME); private static final String SYSTEM_MODULES_MAP_CLASS = "jdk/internal/module/SystemModulesMap"; private static final String SYSTEM_MODULES_CLASS_PREFIX = "jdk/internal/module/SystemModules$"; private static final String ALL_SYSTEM_MODULES_CLASS = SYSTEM_MODULES_CLASS_PREFIX + "all"; private static final String DEFAULT_SYSTEM_MODULES_CLASS = SYSTEM_MODULES_CLASS_PREFIX + "default"; private boolean enabled; public SystemModulesPlugin() { this.enabled = true; } @Override public String getName() { return NAME; } @Override public String getDescription() { return DESCRIPTION; } @Override public Set<State> getState() { return enabled ? EnumSet.of(State.AUTO_ENABLED, State.FUNCTIONAL) : EnumSet.of(State.DISABLED); } @Override public boolean hasArguments() { return true; } @Override public String getArgumentsDescription() { return PluginsResourceBundle.getArgument(NAME); } @Override public void configure(Map<String, String> config) { String arg = config.get(NAME); if (arg != null) { throw new IllegalArgumentException(NAME + ": " + arg); } } @Override public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) { if (!enabled) { throw new PluginException(NAME + " was set"); } // validate, transform (if needed), and add the module-info.class files List<ModuleInfo> moduleInfos = transformModuleInfos(in, out); // generate and add the SystemModuleMap and SystemModules classes Set<String> generated = genSystemModulesClasses(moduleInfos, out); // pass through all other resources in.entries() .filter(data -> !data.path().endsWith("/module-info.class") && !generated.contains(data.path())) .forEach(data -> out.add(data)); return out.build(); } /** * Validates and transforms the module-info.class files in the modules, adding * the ModulePackages class file attribute if needed. * * @return the list of ModuleInfo objects, the first element is java.base */ List<ModuleInfo> transformModuleInfos(ResourcePool in, ResourcePoolBuilder out) { List<ModuleInfo> moduleInfos = new ArrayList<>(); // Sort modules in the topological order so that java.base is always first. new ModuleSorter(in.moduleView()).sorted().forEach(module -> { ResourcePoolEntry data = module.findEntry("module-info.class").orElseThrow( // automatic modules not supported () -> new PluginException("module-info.class not found for " + module.name() + " module") ); assert module.name().equals(data.moduleName()); try { byte[] content = data.contentBytes(); Set<String> packages = module.packages(); ModuleInfo moduleInfo = new ModuleInfo(content, packages); // link-time validation moduleInfo.validateNames(); // check if any exported or open package is not present moduleInfo.validatePackages(); // module-info.class may be overridden to add ModulePackages if (moduleInfo.shouldRewrite()) { data = data.copyWithContent(moduleInfo.getBytes()); } moduleInfos.add(moduleInfo); // add resource pool entry out.add(data); } catch (IOException e) { throw new PluginException(e); } }); return moduleInfos; } /** * Generates the SystemModules classes (at least one) and the SystemModulesMap * class to map initial modules to a SystemModules class. * * @return the resource names of the resources added to the pool */ private Set<String> genSystemModulesClasses(List<ModuleInfo> moduleInfos, ResourcePoolBuilder out) { int moduleCount = moduleInfos.size(); ModuleFinder finder = finderOf(moduleInfos); assert finder.findAll().size() == moduleCount; // map of initial module name to SystemModules class name Map<String, String> map = new LinkedHashMap<>(); // the names of resources written to the pool Set<String> generated = new HashSet<>(); // generate the SystemModules implementation to reconstitute all modules Set<String> allModuleNames = moduleInfos.stream() .map(ModuleInfo::moduleName) .collect(Collectors.toSet()); String rn = genSystemModulesClass(moduleInfos, resolve(finder, allModuleNames), ALL_SYSTEM_MODULES_CLASS, out); generated.add(rn); // generate, if needed, a SystemModules class to reconstitute the modules // needed for the case that the initial module is the unnamed module. String defaultSystemModulesClassName; Configuration cf = resolve(finder, DefaultRoots.compute(finder)); if (cf.modules().size() == moduleCount) { // all modules are resolved so no need to generate a class defaultSystemModulesClassName = ALL_SYSTEM_MODULES_CLASS; } else { defaultSystemModulesClassName = DEFAULT_SYSTEM_MODULES_CLASS; rn = genSystemModulesClass(sublist(moduleInfos, cf), cf, defaultSystemModulesClassName, out); generated.add(rn); } // Generate a SystemModules class for each module with a main class int suffix = 0; for (ModuleInfo mi : moduleInfos) { if (mi.descriptor().mainClass().isPresent()) { String moduleName = mi.moduleName(); cf = resolve(finder, Set.of(moduleName)); if (cf.modules().size() == moduleCount) { // resolves all modules so no need to generate a class map.put(moduleName, ALL_SYSTEM_MODULES_CLASS); } else { String cn = SYSTEM_MODULES_CLASS_PREFIX + (suffix++); rn = genSystemModulesClass(sublist(moduleInfos, cf), cf, cn, out); map.put(moduleName, cn); generated.add(rn); } } } // generate SystemModulesMap rn = genSystemModulesMapClass(ALL_SYSTEM_MODULES_CLASS, defaultSystemModulesClassName, map, out); generated.add(rn); // return the resource names of the generated classes return generated; } /** * Resolves a collection of root modules, with service binding, to create * configuration. */ private Configuration resolve(ModuleFinder finder, Set<String> roots) { return Configuration.empty().resolveAndBind(finder, ModuleFinder.of(), roots); } /** * Returns the list of ModuleInfo objects that correspond to the modules in * the given configuration. */ private List<ModuleInfo> sublist(List<ModuleInfo> moduleInfos, Configuration cf) { Set<String> names = cf.modules() .stream() .map(ResolvedModule::name) .collect(Collectors.toSet()); return moduleInfos.stream() .filter(mi -> names.contains(mi.moduleName())) .collect(Collectors.toList()); } /** * Generate a SystemModules implementation class and add it as a resource. * * @return the name of the class resource added to the pool */ private String genSystemModulesClass(List<ModuleInfo> moduleInfos, Configuration cf, String className, ResourcePoolBuilder out) { SystemModulesClassGenerator generator = new SystemModulesClassGenerator(className, moduleInfos); byte[] bytes = generator.getClassWriter(cf).toByteArray(); String rn = "/java.base/" + className + ".class"; ResourcePoolEntry e = ResourcePoolEntry.create(rn, bytes); out.add(e); return rn; } static class ModuleInfo { private final ByteArrayInputStream bais; private final Attributes attrs; private final Set<String> packages; private final boolean addModulePackages; private ModuleDescriptor descriptor; // may be different that the original one ModuleInfo(byte[] bytes, Set<String> packages) throws IOException { this.bais = new ByteArrayInputStream(bytes); this.packages = packages; this.attrs = jdk.internal.module.ModuleInfo.read(bais, null); // If ModulePackages attribute is present, the packages from this // module descriptor returns the packages in that attribute. // If it's not present, ModuleDescriptor::packages only contains // the exported and open packages from module-info.class this.descriptor = attrs.descriptor(); if (descriptor.isAutomatic()) { throw new InternalError("linking automatic module is not supported"); } // add ModulePackages attribute if this module contains some packages // and ModulePackages is not present this.addModulePackages = packages.size() > 0 && !hasModulePackages(); } String moduleName() { return attrs.descriptor().name(); } ModuleDescriptor descriptor() { return descriptor; } Set<String> packages() { return packages; } ModuleTarget target() { return attrs.target(); } ModuleHashes recordedHashes() { return attrs.recordedHashes(); } ModuleResolution moduleResolution() { return attrs.moduleResolution(); } /** * Validates names in ModuleDescriptor */ void validateNames() { Checks.requireModuleName(descriptor.name()); for (Requires req : descriptor.requires()) { Checks.requireModuleName(req.name()); } for (Exports e : descriptor.exports()) { Checks.requirePackageName(e.source()); if (e.isQualified()) e.targets().forEach(Checks::requireModuleName); } for (Opens opens : descriptor.opens()) { Checks.requirePackageName(opens.source()); if (opens.isQualified()) opens.targets().forEach(Checks::requireModuleName); } for (Provides provides : descriptor.provides()) { Checks.requireServiceTypeName(provides.service()); provides.providers().forEach(Checks::requireServiceProviderName); } for (String service : descriptor.uses()) { Checks.requireServiceTypeName(service); } for (String pn : descriptor.packages()) { Checks.requirePackageName(pn); } for (String pn : packages) { Checks.requirePackageName(pn); } } /** * Validates if exported and open packages are present */ void validatePackages() { Set<String> nonExistPackages = new TreeSet<>(); descriptor.exports().stream() .map(Exports::source) .filter(pn -> !packages.contains(pn)) .forEach(nonExistPackages::add); descriptor.opens().stream() .map(Opens::source) .filter(pn -> !packages.contains(pn)) .forEach(nonExistPackages::add); if (!nonExistPackages.isEmpty()) { throw new PluginException("Packages that are exported or open in " + descriptor.name() + " are not present: " + nonExistPackages); } } boolean hasModulePackages() throws IOException { Set<String> packages = new HashSet<>(); ClassVisitor cv = new ClassVisitor(Opcodes.ASM6) { @Override public ModuleVisitor visitModule(String name, int flags, String version) { return new ModuleVisitor(Opcodes.ASM6) { public void visitPackage(String pn) { packages.add(pn); } }; } }; try (InputStream in = getInputStream()) { // parse module-info.class ClassReader cr = new ClassReader(in); cr.accept(cv, 0); return packages.size() > 0; } } /** * Returns true if module-info.class should be rewritten to add the * ModulePackages attribute. */ boolean shouldRewrite() { return addModulePackages; } /** * Returns the bytes for the (possibly updated) module-info.class. */ byte[] getBytes() throws IOException { try (InputStream in = getInputStream()) { if (shouldRewrite()) { ModuleInfoRewriter rewriter = new ModuleInfoRewriter(in); if (addModulePackages) { rewriter.addModulePackages(packages); } // rewritten module descriptor byte[] bytes = rewriter.getBytes(); try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes)) { this.descriptor = ModuleDescriptor.read(bais); } return bytes; } else { return in.readAllBytes(); } } } /* * Returns the input stream of the module-info.class */ InputStream getInputStream() { bais.reset(); return bais; } class ModuleInfoRewriter extends ByteArrayOutputStream { final ModuleInfoExtender extender; ModuleInfoRewriter(InputStream in) { this.extender = ModuleInfoExtender.newExtender(in); } void addModulePackages(Set<String> packages) { // Add ModulePackages attribute if (packages.size() > 0) { extender.packages(packages); } } byte[] getBytes() throws IOException { extender.write(this); return buf; } } } /** * Generates a SystemModules class to reconstitute the ModuleDescriptor * and other attributes of system modules. */ static class SystemModulesClassGenerator { private static final String MODULE_DESCRIPTOR_BUILDER = "jdk/internal/module/Builder"; private static final String MODULE_DESCRIPTOR_ARRAY_SIGNATURE = "[Ljava/lang/module/ModuleDescriptor;"; private static final String REQUIRES_MODIFIER_CLASSNAME = "java/lang/module/ModuleDescriptor$Requires$Modifier"; private static final String EXPORTS_MODIFIER_CLASSNAME = "java/lang/module/ModuleDescriptor$Exports$Modifier"; private static final String OPENS_MODIFIER_CLASSNAME = "java/lang/module/ModuleDescriptor$Opens$Modifier"; private static final String MODULE_TARGET_CLASSNAME = "jdk/internal/module/ModuleTarget"; private static final String MODULE_TARGET_ARRAY_SIGNATURE = "[Ljdk/internal/module/ModuleTarget;"; private static final String MODULE_HASHES_ARRAY_SIGNATURE = "[Ljdk/internal/module/ModuleHashes;"; private static final String MODULE_RESOLUTION_CLASSNAME = "jdk/internal/module/ModuleResolution"; private static final String MODULE_RESOLUTIONS_ARRAY_SIGNATURE = "[Ljdk/internal/module/ModuleResolution;"; private static final int MAX_LOCAL_VARS = 256; private final int BUILDER_VAR = 0; private final int MD_VAR = 1; // variable for ModuleDescriptor private final int MT_VAR = 1; // variable for ModuleTarget private final int MH_VAR = 1; // variable for ModuleHashes private int nextLocalVar = 2; // index to next local variable // Method visitor for generating the SystemModules::modules() method private MethodVisitor mv; // name of class to generate private final String className; // list of all ModuleDescriptorBuilders, invoked in turn when building. private final List<ModuleInfo> moduleInfos; // A builder to create one single Set instance for a given set of // names or modifiers to reduce the footprint // e.g. target modules of qualified exports private final DedupSetBuilder dedupSetBuilder = new DedupSetBuilder(this::getNextLocalVar); public SystemModulesClassGenerator(String className, List<ModuleInfo> moduleInfos) { this.className = className; this.moduleInfos = moduleInfos; moduleInfos.forEach(mi -> dedups(mi.descriptor())); } private int getNextLocalVar() { return nextLocalVar++; } /* * Adds the given ModuleDescriptor to the system module list. * It performs link-time validation and prepares mapping from various * Sets to SetBuilders to emit an optimized number of sets during build. */ private void dedups(ModuleDescriptor md) { // exports for (Exports e : md.exports()) { dedupSetBuilder.stringSet(e.targets()); dedupSetBuilder.exportsModifiers(e.modifiers()); } // opens for (Opens opens : md.opens()) { dedupSetBuilder.stringSet(opens.targets()); dedupSetBuilder.opensModifiers(opens.modifiers()); } // requires for (Requires r : md.requires()) { dedupSetBuilder.requiresModifiers(r.modifiers()); } // uses dedupSetBuilder.stringSet(md.uses()); } /** * Generate SystemModules class */ public ClassWriter getClassWriter(Configuration cf) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); cw.visit(Opcodes.V1_8, ACC_FINAL+ACC_SUPER, className, null, "java/lang/Object", new String[] { "jdk/internal/module/SystemModules" }); // generate <init> genConstructor(cw); // generate hasSplitPackages genHasSplitPackages(cw); // generate hasIncubatorModules genIncubatorModules(cw); // generate moduleDescriptors genModuleDescriptorsMethod(cw); // generate moduleTargets genModuleTargetsMethod(cw); // generate moduleHashes genModuleHashesMethod(cw); // generate moduleResolutions genModuleResolutionsMethod(cw); // generate moduleReads genModuleReads(cw, cf); // generate concealedPackagesToOpen and exportedPackagesToOpen genXXXPackagesToOpenMethods(cw); return cw; } /** * Generate byteccode for no-arg constructor */ private void genConstructor(ClassWriter cw) { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } /** * Generate bytecode for hasSplitPackages method */ private void genHasSplitPackages(ClassWriter cw) { boolean distinct = moduleInfos.stream() .map(ModuleInfo::packages) .flatMap(Set::stream) .allMatch(new HashSet<>()::add); boolean hasSplitPackages = !distinct; mv = cw.visitMethod(ACC_PUBLIC, "hasSplitPackages", "()Z", "()Z", null); mv.visitCode(); if (hasSplitPackages) { mv.visitInsn(ICONST_1); } else { mv.visitInsn(ICONST_0); } mv.visitInsn(IRETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } /** * Generate bytecode for hasIncubatorModules method */ private void genIncubatorModules(ClassWriter cw) { boolean hasIncubatorModules = moduleInfos.stream() .map(ModuleInfo::moduleResolution) .filter(mres -> (mres != null && mres.hasIncubatingWarning())) .findFirst() .isPresent(); mv = cw.visitMethod(ACC_PUBLIC, "hasIncubatorModules", "()Z", "()Z", null); mv.visitCode(); if (hasIncubatorModules) { mv.visitInsn(ICONST_1); } else { mv.visitInsn(ICONST_0); } mv.visitInsn(IRETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } /** * Generate bytecode for moduleDescriptors method */ private void genModuleDescriptorsMethod(ClassWriter cw) { this.mv = cw.visitMethod(ACC_PUBLIC, "moduleDescriptors", "()" + MODULE_DESCRIPTOR_ARRAY_SIGNATURE, "()" + MODULE_DESCRIPTOR_ARRAY_SIGNATURE, null); mv.visitCode(); pushInt(mv, moduleInfos.size()); mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor"); mv.visitVarInsn(ASTORE, MD_VAR); for (int index = 0; index < moduleInfos.size(); index++) { ModuleInfo minfo = moduleInfos.get(index); new ModuleDescriptorBuilder(minfo.descriptor(), minfo.packages(), index).build(); } mv.visitVarInsn(ALOAD, MD_VAR); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } /** * Generate bytecode for moduleTargets method */ private void genModuleTargetsMethod(ClassWriter cw) { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "moduleTargets", "()" + MODULE_TARGET_ARRAY_SIGNATURE, "()" + MODULE_TARGET_ARRAY_SIGNATURE, null); mv.visitCode(); pushInt(mv, moduleInfos.size()); mv.visitTypeInsn(ANEWARRAY, MODULE_TARGET_CLASSNAME); mv.visitVarInsn(ASTORE, MT_VAR); // if java.base has a ModuleTarget attribute then generate the array // with one element, all other elements will be null. ModuleInfo base = moduleInfos.get(0); if (!base.moduleName().equals("java.base")) throw new InternalError("java.base should be first module in list"); ModuleTarget target = base.target(); int count; if (target != null && target.targetPlatform() != null) { count = 1; } else { count = moduleInfos.size(); } for (int index = 0; index < count; index++) { ModuleInfo minfo = moduleInfos.get(index); if (minfo.target() != null) { mv.visitVarInsn(ALOAD, MT_VAR); pushInt(mv, index); // new ModuleTarget(String) mv.visitTypeInsn(NEW, MODULE_TARGET_CLASSNAME); mv.visitInsn(DUP); mv.visitLdcInsn(minfo.target().targetPlatform()); mv.visitMethodInsn(INVOKESPECIAL, MODULE_TARGET_CLASSNAME, "<init>", "(Ljava/lang/String;)V", false); mv.visitInsn(AASTORE); } } mv.visitVarInsn(ALOAD, MT_VAR); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } /** * Generate bytecode for moduleHashes method */ private void genModuleHashesMethod(ClassWriter cw) { MethodVisitor hmv = cw.visitMethod(ACC_PUBLIC, "moduleHashes", "()" + MODULE_HASHES_ARRAY_SIGNATURE, "()" + MODULE_HASHES_ARRAY_SIGNATURE, null); hmv.visitCode(); pushInt(hmv, moduleInfos.size()); hmv.visitTypeInsn(ANEWARRAY, "jdk/internal/module/ModuleHashes"); hmv.visitVarInsn(ASTORE, MH_VAR); for (int index = 0; index < moduleInfos.size(); index++) { ModuleInfo minfo = moduleInfos.get(index); if (minfo.recordedHashes() != null) { new ModuleHashesBuilder(minfo.recordedHashes(), index, hmv).build(); } } hmv.visitVarInsn(ALOAD, MH_VAR); hmv.visitInsn(ARETURN); hmv.visitMaxs(0, 0); hmv.visitEnd(); } /** * Generate bytecode for moduleResolutions method */ private void genModuleResolutionsMethod(ClassWriter cw) { MethodVisitor mresmv = cw.visitMethod(ACC_PUBLIC, "moduleResolutions", "()" + MODULE_RESOLUTIONS_ARRAY_SIGNATURE, "()" + MODULE_RESOLUTIONS_ARRAY_SIGNATURE, null); mresmv.visitCode(); pushInt(mresmv, moduleInfos.size()); mresmv.visitTypeInsn(ANEWARRAY, MODULE_RESOLUTION_CLASSNAME); mresmv.visitVarInsn(ASTORE, 0); for (int index=0; index < moduleInfos.size(); index++) { ModuleInfo minfo = moduleInfos.get(index); if (minfo.moduleResolution() != null) { mresmv.visitVarInsn(ALOAD, 0); pushInt(mresmv, index); mresmv.visitTypeInsn(NEW, MODULE_RESOLUTION_CLASSNAME); mresmv.visitInsn(DUP); mresmv.visitLdcInsn(minfo.moduleResolution().value()); mresmv.visitMethodInsn(INVOKESPECIAL, MODULE_RESOLUTION_CLASSNAME, "<init>", "(I)V", false); mresmv.visitInsn(AASTORE); } } mresmv.visitVarInsn(ALOAD, 0); mresmv.visitInsn(ARETURN); mresmv.visitMaxs(0, 0); mresmv.visitEnd(); } /** * Generate bytecode for moduleReads method */ private void genModuleReads(ClassWriter cw, Configuration cf) { // module name -> names of modules that it reads Map<String, Set<String>> map = cf.modules().stream() .collect(Collectors.toMap( ResolvedModule::name, m -> m.reads().stream() .map(ResolvedModule::name) .collect(Collectors.toSet()))); generate(cw, "moduleReads", map, true); } /** * Generate concealedPackagesToOpen and exportedPackagesToOpen methods. */ private void genXXXPackagesToOpenMethods(ClassWriter cw) { ModuleFinder finder = finderOf(moduleInfos); IllegalAccessMaps maps = IllegalAccessMaps.generate(finder); generate(cw, "concealedPackagesToOpen", maps.concealedPackagesToOpen(), false); generate(cw, "exportedPackagesToOpen", maps.exportedPackagesToOpen(), false); } /** * Generate method to return {@code Map<String, Set<String>>}. * * If {@code dedup} is true then the values are de-duplicated. */ private void generate(ClassWriter cw, String methodName, Map<String, Set<String>> map, boolean dedup) { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "()Ljava/util/Map;", "()Ljava/util/Map;", null); mv.visitCode(); // map of Set -> local Map<Set<String>, Integer> locals; // generate code to create the sets that are duplicated if (dedup) { Collection<Set<String>> values = map.values(); Set<Set<String>> duplicateSets = values.stream() .distinct() .filter(s -> Collections.frequency(values, s) > 1) .collect(Collectors.toSet()); locals = new HashMap<>(); int index = 1; for (Set<String> s : duplicateSets) { genImmutableSet(mv, s); mv.visitVarInsn(ASTORE, index); locals.put(s, index); if (++index >= MAX_LOCAL_VARS) { break; } } } else { locals = Map.of(); } // new Map$Entry[size] pushInt(mv, map.size()); mv.visitTypeInsn(ANEWARRAY, "java/util/Map$Entry"); int index = 0; for (Map.Entry<String, Set<String>> e : map.entrySet()) { String name = e.getKey(); Set<String> s = e.getValue(); mv.visitInsn(DUP); pushInt(mv, index); mv.visitLdcInsn(name); // if de-duplicated then load the local, otherwise generate code Integer varIndex = locals.get(s); if (varIndex == null) { genImmutableSet(mv, s); } else { mv.visitVarInsn(ALOAD, varIndex); } String desc = "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/Map$Entry;"; mv.visitMethodInsn(INVOKESTATIC, "java/util/Map", "entry", desc, true); mv.visitInsn(AASTORE); index++; } // invoke Map.ofEntries(Map$Entry[]) mv.visitMethodInsn(INVOKESTATIC, "java/util/Map", "ofEntries", "([Ljava/util/Map$Entry;)Ljava/util/Map;", true); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } /** * Generate code to generate an immutable set. */ private void genImmutableSet(MethodVisitor mv, Set<String> set) { int size = set.size(); // use Set.of(Object[]) when there are more than 2 elements // use Set.of(Object) or Set.of(Object, Object) when fewer if (size > 2) { pushInt(mv, size); mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); int i = 0; for (String element : set) { mv.visitInsn(DUP); pushInt(mv, i); mv.visitLdcInsn(element); mv.visitInsn(AASTORE); i++; } mv.visitMethodInsn(INVOKESTATIC, "java/util/Set", "of", "([Ljava/lang/Object;)Ljava/util/Set;", true); } else { StringBuilder sb = new StringBuilder("("); for (String element : set) { mv.visitLdcInsn(element); sb.append("Ljava/lang/Object;"); } sb.append(")Ljava/util/Set;"); mv.visitMethodInsn(INVOKESTATIC, "java/util/Set", "of", sb.toString(), true); } } class ModuleDescriptorBuilder { static final String BUILDER_TYPE = "Ljdk/internal/module/Builder;"; static final String EXPORTS_TYPE = "Ljava/lang/module/ModuleDescriptor$Exports;"; static final String OPENS_TYPE = "Ljava/lang/module/ModuleDescriptor$Opens;"; static final String PROVIDES_TYPE = "Ljava/lang/module/ModuleDescriptor$Provides;"; static final String REQUIRES_TYPE = "Ljava/lang/module/ModuleDescriptor$Requires;"; // method signature for static Builder::newExports, newOpens, // newProvides, newRequires methods static final String EXPORTS_MODIFIER_SET_STRING_SET_SIG = "(Ljava/util/Set;Ljava/lang/String;Ljava/util/Set;)" + EXPORTS_TYPE; static final String EXPORTS_MODIFIER_SET_STRING_SIG = "(Ljava/util/Set;Ljava/lang/String;)" + EXPORTS_TYPE; static final String OPENS_MODIFIER_SET_STRING_SET_SIG = "(Ljava/util/Set;Ljava/lang/String;Ljava/util/Set;)" + OPENS_TYPE; static final String OPENS_MODIFIER_SET_STRING_SIG = "(Ljava/util/Set;Ljava/lang/String;)" + OPENS_TYPE; static final String PROVIDES_STRING_LIST_SIG = "(Ljava/lang/String;Ljava/util/List;)" + PROVIDES_TYPE; static final String REQUIRES_SET_STRING_SIG = "(Ljava/util/Set;Ljava/lang/String;)" + REQUIRES_TYPE; static final String REQUIRES_SET_STRING_STRING_SIG = "(Ljava/util/Set;Ljava/lang/String;Ljava/lang/String;)" + REQUIRES_TYPE; // method signature for Builder instance methods that // return this Builder instance static final String EXPORTS_ARRAY_SIG = "([" + EXPORTS_TYPE + ")" + BUILDER_TYPE; static final String OPENS_ARRAY_SIG = "([" + OPENS_TYPE + ")" + BUILDER_TYPE; static final String PROVIDES_ARRAY_SIG = "([" + PROVIDES_TYPE + ")" + BUILDER_TYPE; static final String REQUIRES_ARRAY_SIG = "([" + REQUIRES_TYPE + ")" + BUILDER_TYPE; static final String SET_SIG = "(Ljava/util/Set;)" + BUILDER_TYPE; static final String STRING_SIG = "(Ljava/lang/String;)" + BUILDER_TYPE; static final String BOOLEAN_SIG = "(Z)" + BUILDER_TYPE; final ModuleDescriptor md; final Set<String> packages; final int index; ModuleDescriptorBuilder(ModuleDescriptor md, Set<String> packages, int index) { if (md.isAutomatic()) { throw new InternalError("linking automatic module is not supported"); } this.md = md; this.packages = packages; this.index = index; } void build() { // new jdk.internal.module.Builder newBuilder(); // requires requires(md.requires()); // exports exports(md.exports()); // opens opens(md.opens()); // uses uses(md.uses()); // provides provides(md.provides()); // all packages packages(packages); // version md.version().ifPresent(this::version); // main class md.mainClass().ifPresent(this::mainClass); putModuleDescriptor(); } void newBuilder() { mv.visitTypeInsn(NEW, MODULE_DESCRIPTOR_BUILDER); mv.visitInsn(DUP); mv.visitLdcInsn(md.name()); mv.visitMethodInsn(INVOKESPECIAL, MODULE_DESCRIPTOR_BUILDER, "<init>", "(Ljava/lang/String;)V", false); mv.visitVarInsn(ASTORE, BUILDER_VAR); mv.visitVarInsn(ALOAD, BUILDER_VAR); if (md.isOpen()) { setModuleBit("open", true); } if (md.modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) { setModuleBit("synthetic", true); } if (md.modifiers().contains(ModuleDescriptor.Modifier.MANDATED)) { setModuleBit("mandated", true); } } /* * Invoke Builder.<methodName>(boolean value) */ void setModuleBit(String methodName, boolean value) { mv.visitVarInsn(ALOAD, BUILDER_VAR); if (value) { mv.visitInsn(ICONST_1); } else { mv.visitInsn(ICONST_0); } mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, methodName, BOOLEAN_SIG, false); mv.visitInsn(POP); } /* * Put ModuleDescriptor into the modules array */ void putModuleDescriptor() { mv.visitVarInsn(ALOAD, MD_VAR); pushInt(mv, index); mv.visitVarInsn(ALOAD, BUILDER_VAR); mv.visitLdcInsn(md.hashCode()); mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, "build", "(I)Ljava/lang/module/ModuleDescriptor;", false); mv.visitInsn(AASTORE); } /* * Call Builder::newRequires to create Requires instances and * then pass it to the builder by calling: * Builder.requires(Requires[]) * */ void requires(Set<Requires> requires) { mv.visitVarInsn(ALOAD, BUILDER_VAR); pushInt(mv, requires.size()); mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Requires"); int arrayIndex = 0; for (Requires require : requires) { String compiledVersion = null; if (require.compiledVersion().isPresent()) { compiledVersion = require.compiledVersion().get().toString(); } mv.visitInsn(DUP); // arrayref pushInt(mv, arrayIndex++); newRequires(require.modifiers(), require.name(), compiledVersion); mv.visitInsn(AASTORE); } mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, "requires", REQUIRES_ARRAY_SIG, false); } /* * Invoke Builder.newRequires(Set<Modifier> mods, String mn, String compiledVersion) * * Set<Modifier> mods = ... * Builder.newRequires(mods, mn, compiledVersion); */ void newRequires(Set<Requires.Modifier> mods, String name, String compiledVersion) { int varIndex = dedupSetBuilder.indexOfRequiresModifiers(mods); mv.visitVarInsn(ALOAD, varIndex); mv.visitLdcInsn(name); if (compiledVersion != null) { mv.visitLdcInsn(compiledVersion); mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER, "newRequires", REQUIRES_SET_STRING_STRING_SIG, false); } else { mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER, "newRequires", REQUIRES_SET_STRING_SIG, false); } } /* * Call Builder::newExports to create Exports instances and * then pass it to the builder by calling: * Builder.exports(Exports[]) * */ void exports(Set<Exports> exports) { mv.visitVarInsn(ALOAD, BUILDER_VAR); pushInt(mv, exports.size()); mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Exports"); int arrayIndex = 0; for (Exports export : exports) { mv.visitInsn(DUP); // arrayref pushInt(mv, arrayIndex++); newExports(export.modifiers(), export.source(), export.targets()); mv.visitInsn(AASTORE); } mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, "exports", EXPORTS_ARRAY_SIG, false); } /* * Invoke * Builder.newExports(Set<Exports.Modifier> ms, String pn, * Set<String> targets) * or * Builder.newExports(Set<Exports.Modifier> ms, String pn) * * Set<String> targets = new HashSet<>(); * targets.add(t); * : * : * * Set<Modifier> mods = ... * Builder.newExports(mods, pn, targets); */ void newExports(Set<Exports.Modifier> ms, String pn, Set<String> targets) { int modifiersSetIndex = dedupSetBuilder.indexOfExportsModifiers(ms); if (!targets.isEmpty()) { int stringSetIndex = dedupSetBuilder.indexOfStringSet(targets); mv.visitVarInsn(ALOAD, modifiersSetIndex); mv.visitLdcInsn(pn); mv.visitVarInsn(ALOAD, stringSetIndex); mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER, "newExports", EXPORTS_MODIFIER_SET_STRING_SET_SIG, false); } else { mv.visitVarInsn(ALOAD, modifiersSetIndex); mv.visitLdcInsn(pn); mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER, "newExports", EXPORTS_MODIFIER_SET_STRING_SIG, false); } } /** * Call Builder::newOpens to create Opens instances and * then pass it to the builder by calling: * Builder.opens(Opens[]) */ void opens(Set<Opens> opens) { mv.visitVarInsn(ALOAD, BUILDER_VAR); pushInt(mv, opens.size()); mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Opens"); int arrayIndex = 0; for (Opens open : opens) { mv.visitInsn(DUP); // arrayref pushInt(mv, arrayIndex++); newOpens(open.modifiers(), open.source(), open.targets()); mv.visitInsn(AASTORE); } mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, "opens", OPENS_ARRAY_SIG, false); } /* * Invoke * Builder.newOpens(Set<Opens.Modifier> ms, String pn, * Set<String> targets) * or * Builder.newOpens(Set<Opens.Modifier> ms, String pn) * * Set<String> targets = new HashSet<>(); * targets.add(t); * : * : * * Set<Modifier> mods = ... * Builder.newOpens(mods, pn, targets); */ void newOpens(Set<Opens.Modifier> ms, String pn, Set<String> targets) { int modifiersSetIndex = dedupSetBuilder.indexOfOpensModifiers(ms); if (!targets.isEmpty()) { int stringSetIndex = dedupSetBuilder.indexOfStringSet(targets); mv.visitVarInsn(ALOAD, modifiersSetIndex); mv.visitLdcInsn(pn); mv.visitVarInsn(ALOAD, stringSetIndex); mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER, "newOpens", OPENS_MODIFIER_SET_STRING_SET_SIG, false); } else { mv.visitVarInsn(ALOAD, modifiersSetIndex); mv.visitLdcInsn(pn); mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER, "newOpens", OPENS_MODIFIER_SET_STRING_SIG, false); } } /* * Invoke Builder.uses(Set<String> uses) */ void uses(Set<String> uses) { int varIndex = dedupSetBuilder.indexOfStringSet(uses); mv.visitVarInsn(ALOAD, BUILDER_VAR); mv.visitVarInsn(ALOAD, varIndex); mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, "uses", SET_SIG, false); mv.visitInsn(POP); } /* * Call Builder::newProvides to create Provides instances and * then pass it to the builder by calling: * Builder.provides(Provides[] provides) * */ void provides(Collection<Provides> provides) { mv.visitVarInsn(ALOAD, BUILDER_VAR); pushInt(mv, provides.size()); mv.visitTypeInsn(ANEWARRAY, "java/lang/module/ModuleDescriptor$Provides"); int arrayIndex = 0; for (Provides provide : provides) { mv.visitInsn(DUP); // arrayref pushInt(mv, arrayIndex++); newProvides(provide.service(), provide.providers()); mv.visitInsn(AASTORE); } mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, "provides", PROVIDES_ARRAY_SIG, false); } /* * Invoke Builder.newProvides(String service, Set<String> providers) * * Set<String> providers = new HashSet<>(); * providers.add(impl); * : * : * Builder.newProvides(service, providers); */ void newProvides(String service, List<String> providers) { mv.visitLdcInsn(service); pushInt(mv, providers.size()); mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); int arrayIndex = 0; for (String provider : providers) { mv.visitInsn(DUP); // arrayref pushInt(mv, arrayIndex++); mv.visitLdcInsn(provider); mv.visitInsn(AASTORE); } mv.visitMethodInsn(INVOKESTATIC, "java/util/List", "of", "([Ljava/lang/Object;)Ljava/util/List;", true); mv.visitMethodInsn(INVOKESTATIC, MODULE_DESCRIPTOR_BUILDER, "newProvides", PROVIDES_STRING_LIST_SIG, false); } /* * Invoke Builder.packages(String pn) */ void packages(Set<String> packages) { int varIndex = dedupSetBuilder.newStringSet(packages); mv.visitVarInsn(ALOAD, BUILDER_VAR); mv.visitVarInsn(ALOAD, varIndex); mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, "packages", SET_SIG, false); mv.visitInsn(POP); } /* * Invoke Builder.mainClass(String cn) */ void mainClass(String cn) { mv.visitVarInsn(ALOAD, BUILDER_VAR); mv.visitLdcInsn(cn); mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, "mainClass", STRING_SIG, false); mv.visitInsn(POP); } /* * Invoke Builder.version(Version v); */ void version(Version v) { mv.visitVarInsn(ALOAD, BUILDER_VAR); mv.visitLdcInsn(v.toString()); mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, "version", STRING_SIG, false); mv.visitInsn(POP); } void invokeBuilderMethod(String methodName, String value) { mv.visitVarInsn(ALOAD, BUILDER_VAR); mv.visitLdcInsn(value); mv.visitMethodInsn(INVOKEVIRTUAL, MODULE_DESCRIPTOR_BUILDER, methodName, STRING_SIG, false); mv.visitInsn(POP); } } class ModuleHashesBuilder { private static final String MODULE_HASHES_BUILDER = "jdk/internal/module/ModuleHashes$Builder"; private static final String MODULE_HASHES_BUILDER_TYPE = "L" + MODULE_HASHES_BUILDER + ";"; static final String STRING_BYTE_ARRAY_SIG = "(Ljava/lang/String;[B)" + MODULE_HASHES_BUILDER_TYPE; final ModuleHashes recordedHashes; final MethodVisitor hmv; final int index; ModuleHashesBuilder(ModuleHashes hashes, int index, MethodVisitor hmv) { this.recordedHashes = hashes; this.hmv = hmv; this.index = index; } /** * Build ModuleHashes */ void build() { if (recordedHashes == null) return; // new jdk.internal.module.ModuleHashes.Builder newModuleHashesBuilder(); // Invoke ModuleHashes.Builder::hashForModule recordedHashes .names() .forEach(mn -> hashForModule(mn, recordedHashes.hashFor(mn))); // Put ModuleHashes into the hashes array pushModuleHashes(); } /* * Create ModuleHashes.Builder instance */ void newModuleHashesBuilder() { hmv.visitTypeInsn(NEW, MODULE_HASHES_BUILDER); hmv.visitInsn(DUP); hmv.visitLdcInsn(recordedHashes.algorithm()); pushInt(hmv, ((4 * recordedHashes.names().size()) / 3) + 1); hmv.visitMethodInsn(INVOKESPECIAL, MODULE_HASHES_BUILDER, "<init>", "(Ljava/lang/String;I)V", false); hmv.visitVarInsn(ASTORE, BUILDER_VAR); hmv.visitVarInsn(ALOAD, BUILDER_VAR); } /* * Invoke ModuleHashes.Builder::build and put the returned * ModuleHashes to the hashes array */ void pushModuleHashes() { hmv.visitVarInsn(ALOAD, MH_VAR); pushInt(hmv, index); hmv.visitVarInsn(ALOAD, BUILDER_VAR); hmv.visitMethodInsn(INVOKEVIRTUAL, MODULE_HASHES_BUILDER, "build", "()Ljdk/internal/module/ModuleHashes;", false); hmv.visitInsn(AASTORE); } /* * Invoke ModuleHashes.Builder.hashForModule(String name, byte[] hash); */ void hashForModule(String name, byte[] hash) { hmv.visitVarInsn(ALOAD, BUILDER_VAR); hmv.visitLdcInsn(name); pushInt(hmv, hash.length); hmv.visitIntInsn(NEWARRAY, T_BYTE); for (int i = 0; i < hash.length; i++) { hmv.visitInsn(DUP); // arrayref pushInt(hmv, i); hmv.visitIntInsn(BIPUSH, hash[i]); hmv.visitInsn(BASTORE); } hmv.visitMethodInsn(INVOKEVIRTUAL, MODULE_HASHES_BUILDER, "hashForModule", STRING_BYTE_ARRAY_SIG, false); hmv.visitInsn(POP); } } /* * Wraps set creation, ensuring identical sets are properly deduplicated. */ class DedupSetBuilder { // map Set<String> to a specialized builder to allow them to be // deduplicated as they are requested final Map<Set<String>, SetBuilder<String>> stringSets = new HashMap<>(); // map Set<Requires.Modifier> to a specialized builder to allow them to be // deduplicated as they are requested final Map<Set<Requires.Modifier>, EnumSetBuilder<Requires.Modifier>> requiresModifiersSets = new HashMap<>(); // map Set<Exports.Modifier> to a specialized builder to allow them to be // deduplicated as they are requested final Map<Set<Exports.Modifier>, EnumSetBuilder<Exports.Modifier>> exportsModifiersSets = new HashMap<>(); // map Set<Opens.Modifier> to a specialized builder to allow them to be // deduplicated as they are requested final Map<Set<Opens.Modifier>, EnumSetBuilder<Opens.Modifier>> opensModifiersSets = new HashMap<>(); private final int stringSetVar; private final int enumSetVar; private final IntSupplier localVarSupplier; DedupSetBuilder(IntSupplier localVarSupplier) { this.stringSetVar = localVarSupplier.getAsInt(); this.enumSetVar = localVarSupplier.getAsInt(); this.localVarSupplier = localVarSupplier; } /* * Add the given set of strings to this builder. */ void stringSet(Set<String> strings) { stringSets.computeIfAbsent(strings, s -> new SetBuilder<>(s, stringSetVar, localVarSupplier) ).increment(); } /* * Add the given set of Exports.Modifiers */ void exportsModifiers(Set<Exports.Modifier> mods) { exportsModifiersSets.computeIfAbsent(mods, s -> new EnumSetBuilder<>(s, EXPORTS_MODIFIER_CLASSNAME, enumSetVar, localVarSupplier) ).increment(); } /* * Add the given set of Opens.Modifiers */ void opensModifiers(Set<Opens.Modifier> mods) { opensModifiersSets.computeIfAbsent(mods, s -> new EnumSetBuilder<>(s, OPENS_MODIFIER_CLASSNAME, enumSetVar, localVarSupplier) ).increment(); } /* * Add the given set of Requires.Modifiers */ void requiresModifiers(Set<Requires.Modifier> mods) { requiresModifiersSets.computeIfAbsent(mods, s -> new EnumSetBuilder<>(s, REQUIRES_MODIFIER_CLASSNAME, enumSetVar, localVarSupplier) ).increment(); } /* * Retrieve the index to the given set of Strings. Emit code to * generate it when SetBuilder::build is called. */ int indexOfStringSet(Set<String> names) { return stringSets.get(names).build(); } /* * Retrieve the index to the given set of Exports.Modifier. * Emit code to generate it when EnumSetBuilder::build is called. */ int indexOfExportsModifiers(Set<Exports.Modifier> mods) { return exportsModifiersSets.get(mods).build(); } /** * Retrieve the index to the given set of Opens.Modifier. * Emit code to generate it when EnumSetBuilder::build is called. */ int indexOfOpensModifiers(Set<Opens.Modifier> mods) { return opensModifiersSets.get(mods).build(); } /* * Retrieve the index to the given set of Requires.Modifier. * Emit code to generate it when EnumSetBuilder::build is called. */ int indexOfRequiresModifiers(Set<Requires.Modifier> mods) { return requiresModifiersSets.get(mods).build(); } /* * Build a new string set without any attempt to deduplicate it. */ int newStringSet(Set<String> names) { int index = new SetBuilder<>(names, stringSetVar, localVarSupplier).build(); assert index == stringSetVar; return index; } } /* * SetBuilder generates bytecode to create one single instance of Set * for a given set of elements and assign to a local variable slot. * When there is only one single reference to a Set<T>, * it will reuse defaultVarIndex. For a Set with multiple references, * it will use a new local variable retrieved from the nextLocalVar */ class SetBuilder<T> { private final Set<T> elements; private final int defaultVarIndex; private final IntSupplier nextLocalVar; private int refCount; private int localVarIndex; SetBuilder(Set<T> elements, int defaultVarIndex, IntSupplier nextLocalVar) { this.elements = elements; this.defaultVarIndex = defaultVarIndex; this.nextLocalVar = nextLocalVar; } /* * Increments the number of references to this particular set. */ final void increment() { refCount++; } /** * Generate the appropriate instructions to load an object reference * to the element onto the stack. */ void visitElement(T element, MethodVisitor mv) { mv.visitLdcInsn(element); } /* * Build bytecode for the Set represented by this builder, * or get the local variable index of a previously generated set * (in the local scope). * * @return local variable index of the generated set. */ final int build() { int index = localVarIndex; if (localVarIndex == 0) { // if non-empty and more than one set reference this builder, // emit to a unique local index = refCount <= 1 ? defaultVarIndex : nextLocalVar.getAsInt(); if (index < MAX_LOCAL_VARS) { localVarIndex = index; } else { // overflow: disable optimization by using localVarIndex = 0 index = defaultVarIndex; } generateSetOf(index); } return index; } private void generateSetOf(int index) { if (elements.size() <= 10) { // call Set.of(e1, e2, ...) StringBuilder sb = new StringBuilder("("); for (T t : elements) { sb.append("Ljava/lang/Object;"); visitElement(t, mv); } sb.append(")Ljava/util/Set;"); mv.visitMethodInsn(INVOKESTATIC, "java/util/Set", "of", sb.toString(), true); } else { // call Set.of(E... elements) pushInt(mv, elements.size()); mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); int arrayIndex = 0; for (T t : elements) { mv.visitInsn(DUP); // arrayref pushInt(mv, arrayIndex); visitElement(t, mv); // value mv.visitInsn(AASTORE); arrayIndex++; } mv.visitMethodInsn(INVOKESTATIC, "java/util/Set", "of", "([Ljava/lang/Object;)Ljava/util/Set;", true); } mv.visitVarInsn(ASTORE, index); } } /* * Generates bytecode to create one single instance of EnumSet * for a given set of modifiers and assign to a local variable slot. */ class EnumSetBuilder<T> extends SetBuilder<T> { private final String className; EnumSetBuilder(Set<T> modifiers, String className, int defaultVarIndex, IntSupplier nextLocalVar) { super(modifiers, defaultVarIndex, nextLocalVar); this.className = className; } /** * Loads an Enum field. */ void visitElement(T t, MethodVisitor mv) { mv.visitFieldInsn(GETSTATIC, className, t.toString(), "L" + className + ";"); } } } /** * Generate SystemModulesMap and add it as a resource. * * @return the name of the class resource added to the pool */ private String genSystemModulesMapClass(String allSystemModulesClassName, String defaultSystemModulesClassName, Map<String, String> map, ResourcePoolBuilder out) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES); cw.visit(Opcodes.V1_8, ACC_FINAL+ACC_SUPER, SYSTEM_MODULES_MAP_CLASS, null, "java/lang/Object", null); // <init> MethodVisitor mv = cw.visitMethod(0, "<init>", "()V", null, null); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); // allSystemModules() mv = cw.visitMethod(ACC_STATIC, "allSystemModules", "()Ljdk/internal/module/SystemModules;", "()Ljdk/internal/module/SystemModules;", null); mv.visitCode(); mv.visitTypeInsn(NEW, allSystemModulesClassName); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, allSystemModulesClassName, "<init>", "()V", false); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); // defaultSystemModules() mv = cw.visitMethod(ACC_STATIC, "defaultSystemModules", "()Ljdk/internal/module/SystemModules;", "()Ljdk/internal/module/SystemModules;", null); mv.visitCode(); mv.visitTypeInsn(NEW, defaultSystemModulesClassName); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, defaultSystemModulesClassName, "<init>", "()V", false); mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); // moduleNames() mv = cw.visitMethod(ACC_STATIC, "moduleNames", "()[Ljava/lang/String;", "()[Ljava/lang/String;", null); mv.visitCode(); pushInt(mv, map.size()); mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); int index = 0; for (String moduleName : map.keySet()) { mv.visitInsn(DUP); // arrayref pushInt(mv, index); mv.visitLdcInsn(moduleName); mv.visitInsn(AASTORE); index++; } mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); // classNames() mv = cw.visitMethod(ACC_STATIC, "classNames", "()[Ljava/lang/String;", "()[Ljava/lang/String;", null); mv.visitCode(); pushInt(mv, map.size()); mv.visitTypeInsn(ANEWARRAY, "java/lang/String"); index = 0; for (String className : map.values()) { mv.visitInsn(DUP); // arrayref pushInt(mv, index); mv.visitLdcInsn(className.replace('/', '.')); mv.visitInsn(AASTORE); index++; } mv.visitInsn(ARETURN); mv.visitMaxs(0, 0); mv.visitEnd(); // write the class file to the pool as a resource String rn = "/java.base/" + SYSTEM_MODULES_MAP_CLASS + ".class"; ResourcePoolEntry e = ResourcePoolEntry.create(rn, cw.toByteArray()); out.add(e); return rn; } /** * Pushes an int constant */ private static void pushInt(MethodVisitor mv, int value) { if (value <= 5) { mv.visitInsn(ICONST_0 + value); } else if (value < Byte.MAX_VALUE) { mv.visitIntInsn(BIPUSH, value); } else if (value < Short.MAX_VALUE) { mv.visitIntInsn(SIPUSH, value); } else { throw new IllegalArgumentException("exceed limit: " + value); } } /** * Returns a module finder that finds all modules in the given list */ private static ModuleFinder finderOf(Collection<ModuleInfo> moduleInfos) { Supplier<ModuleReader> readerSupplier = () -> null; Map<String, ModuleReference> namesToReference = new HashMap<>(); for (ModuleInfo mi : moduleInfos) { String name = mi.moduleName(); ModuleReference mref = new ModuleReferenceImpl(mi.descriptor(), URI.create("jrt:/" + name), readerSupplier, null, mi.target(), null, null, mi.moduleResolution()); namesToReference.put(name, mref); } return new ModuleFinder() { @Override public Optional<ModuleReference> find(String name) { Objects.requireNonNull(name); return Optional.ofNullable(namesToReference.get(name)); } @Override public Set<ModuleReference> findAll() { return new HashSet<>(namesToReference.values()); } }; } }
⏎ jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
Or download all of them as a single archive file:
File name: jdk.jlink-11.0.1-src.zip File size: 155677 bytes Release date: 2018-11-04 Download
⇒ JDK 11 jdk.jshell.jmod - JShell Tool
2020-06-30, 25259👍, 0💬
Popular Posts:
Jetty provides an HTTP server, HTTP client, and javax.servlet container. These components are open s...
How to download and install JDK (Java Development Kit) 6? If you want to write Java applications, yo...
How to run "javac" command from JDK tools.jar file? "javac" is the Java compiler command that allows...
What Is commons-codec-1.4.jar? commons-codec-1.4.jar is the JAR file for Apache Commons Codec 1.4, w...
commons-lang-1.0.1.jar is the JAR file for Apache Commons Lang 1.0.1, which provides a host of helpe...