Search in sources :

Example 1 with ModuleDescriptor

use of java.lang.module.ModuleDescriptor in project Bytecoder by mirkosertic.

the class Module method initExportsAndOpens.

/**
 * Initialize/setup a module's exports.
 *
 * @param m the module
 * @param nameToSource map of module name to Module for modules that m reads
 * @param nameToModule map of module name to Module for modules in the layer
 *                     under construction
 * @param parents the parent layers
 */
private static void initExportsAndOpens(Module m, Map<String, Module> nameToSource, Map<String, Module> nameToModule, List<ModuleLayer> parents) {
    ModuleDescriptor descriptor = m.getDescriptor();
    Map<String, Set<Module>> openPackages = new HashMap<>();
    Map<String, Set<Module>> exportedPackages = new HashMap<>();
    // process the open packages first
    for (Opens opens : descriptor.opens()) {
        String source = opens.source();
        if (opens.isQualified()) {
            // qualified opens
            Set<Module> targets = new HashSet<>();
            for (String target : opens.targets()) {
                Module m2 = findModule(target, nameToSource, nameToModule, parents);
                if (m2 != null) {
                    addExports0(m, source, m2);
                    targets.add(m2);
                }
            }
            if (!targets.isEmpty()) {
                openPackages.put(source, targets);
            }
        } else {
            // unqualified opens
            addExportsToAll0(m, source);
            openPackages.put(source, EVERYONE_SET);
        }
    }
    // next the exports, skipping exports when the package is open
    for (Exports exports : descriptor.exports()) {
        String source = exports.source();
        // skip export if package is already open to everyone
        Set<Module> openToTargets = openPackages.get(source);
        if (openToTargets != null && openToTargets.contains(EVERYONE_MODULE))
            continue;
        if (exports.isQualified()) {
            // qualified exports
            Set<Module> targets = new HashSet<>();
            for (String target : exports.targets()) {
                Module m2 = findModule(target, nameToSource, nameToModule, parents);
                if (m2 != null) {
                    // skip qualified export if already open to m2
                    if (openToTargets == null || !openToTargets.contains(m2)) {
                        addExports0(m, source, m2);
                        targets.add(m2);
                    }
                }
            }
            if (!targets.isEmpty()) {
                exportedPackages.put(source, targets);
            }
        } else {
            // unqualified exports
            addExportsToAll0(m, source);
            exportedPackages.put(source, EVERYONE_SET);
        }
    }
    if (!openPackages.isEmpty())
        m.openPackages = openPackages;
    if (!exportedPackages.isEmpty())
        m.exportedPackages = exportedPackages;
}
Also used : ModuleDescriptor(java.lang.module.ModuleDescriptor) HashSet(java.util.HashSet) Set(java.util.Set) Opens(java.lang.module.ModuleDescriptor.Opens) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ResolvedModule(java.lang.module.ResolvedModule) Exports(java.lang.module.ModuleDescriptor.Exports) HashSet(java.util.HashSet)

Example 2 with ModuleDescriptor

use of java.lang.module.ModuleDescriptor in project Bytecoder by mirkosertic.

the class Module method defineModules.

// -- creating Module objects --
/**
 * Defines all module in a configuration to the runtime.
 *
 * @return a map of module name to runtime {@code Module}
 *
 * @throws IllegalArgumentException
 *         If defining any of the modules to the VM fails
 */
static Map<String, Module> defineModules(Configuration cf, Function<String, ClassLoader> clf, ModuleLayer layer) {
    boolean isBootLayer = (ModuleLayer.boot() == null);
    int cap = (int) (cf.modules().size() / 0.75f + 1.0f);
    Map<String, Module> nameToModule = new HashMap<>(cap);
    Map<String, ClassLoader> nameToLoader = new HashMap<>(cap);
    Set<ClassLoader> loaders = new HashSet<>();
    boolean hasPlatformModules = false;
    // map each module to a class loader
    for (ResolvedModule resolvedModule : cf.modules()) {
        String name = resolvedModule.name();
        ClassLoader loader = clf.apply(name);
        nameToLoader.put(name, loader);
        if (loader == null || loader == ClassLoaders.platformClassLoader()) {
            if (!(clf instanceof ModuleLoaderMap.Mapper)) {
                throw new IllegalArgumentException("loader can't be 'null'" + " or the platform class loader");
            }
            hasPlatformModules = true;
        } else {
            loaders.add(loader);
        }
    }
    // define each module in the configuration to the VM
    for (ResolvedModule resolvedModule : cf.modules()) {
        ModuleReference mref = resolvedModule.reference();
        ModuleDescriptor descriptor = mref.descriptor();
        String name = descriptor.name();
        ClassLoader loader = nameToLoader.get(name);
        Module m;
        if (loader == null && name.equals("java.base")) {
            // java.base is already defined to the VM
            m = Object.class.getModule();
        } else {
            URI uri = mref.location().orElse(null);
            m = new Module(layer, loader, descriptor, uri);
        }
        nameToModule.put(name, m);
    }
    // setup readability and exports/opens
    for (ResolvedModule resolvedModule : cf.modules()) {
        ModuleReference mref = resolvedModule.reference();
        ModuleDescriptor descriptor = mref.descriptor();
        String mn = descriptor.name();
        Module m = nameToModule.get(mn);
        assert m != null;
        // reads
        Set<Module> reads = new HashSet<>();
        // name -> source Module when in parent layer
        Map<String, Module> nameToSource = Collections.emptyMap();
        for (ResolvedModule other : resolvedModule.reads()) {
            Module m2 = null;
            if (other.configuration() == cf) {
                // this configuration
                m2 = nameToModule.get(other.name());
                assert m2 != null;
            } else {
                // parent layer
                for (ModuleLayer parent : layer.parents()) {
                    m2 = findModule(parent, other);
                    if (m2 != null)
                        break;
                }
                assert m2 != null;
                if (nameToSource.isEmpty())
                    nameToSource = new HashMap<>();
                nameToSource.put(other.name(), m2);
            }
            reads.add(m2);
            // update VM view
            addReads0(m, m2);
        }
        m.reads = reads;
        // automatic modules read all unnamed modules
        if (descriptor.isAutomatic()) {
            m.implAddReads(ALL_UNNAMED_MODULE, true);
        }
        // exports and opens, skipped for open and automatic
        if (!descriptor.isOpen() && !descriptor.isAutomatic()) {
            if (isBootLayer && descriptor.opens().isEmpty()) {
                // no open packages, no qualified exports to modules in parent layers
                initExports(m, nameToModule);
            } else {
                initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
            }
        }
    }
    // then register the modules in the class loader's services catalog
    if (hasPlatformModules) {
        ClassLoader pcl = ClassLoaders.platformClassLoader();
        ServicesCatalog bootCatalog = BootLoader.getServicesCatalog();
        ServicesCatalog pclCatalog = ServicesCatalog.getServicesCatalog(pcl);
        for (ResolvedModule resolvedModule : cf.modules()) {
            ModuleReference mref = resolvedModule.reference();
            ModuleDescriptor descriptor = mref.descriptor();
            if (!descriptor.provides().isEmpty()) {
                String name = descriptor.name();
                Module m = nameToModule.get(name);
                ClassLoader loader = nameToLoader.get(name);
                if (loader == null) {
                    bootCatalog.register(m);
                } else if (loader == pcl) {
                    pclCatalog.register(m);
                }
            }
        }
    }
    // record that there is a layer with modules defined to the class loader
    for (ClassLoader loader : loaders) {
        layer.bindToLoader(loader);
    }
    return nameToModule;
}
Also used : HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ServicesCatalog(jdk.internal.module.ServicesCatalog) URI(java.net.URI) ModuleDescriptor(java.lang.module.ModuleDescriptor) ResolvedModule(java.lang.module.ResolvedModule) ModuleReference(java.lang.module.ModuleReference) BuiltinClassLoader(jdk.internal.loader.BuiltinClassLoader) ResolvedModule(java.lang.module.ResolvedModule) HashSet(java.util.HashSet)

Example 3 with ModuleDescriptor

use of java.lang.module.ModuleDescriptor in project Bytecoder by mirkosertic.

the class ModuleLayer method checkForDuplicatePkgs.

/**
 * Checks a configuration and the module-to-loader mapping to ensure that
 * no two modules mapped to the same class loader have the same package.
 * It also checks that no two automatic modules have the same package.
 *
 * @throws LayerInstantiationException
 */
private static void checkForDuplicatePkgs(Configuration cf, Function<String, ClassLoader> clf) {
    // HashMap allows null keys
    Map<ClassLoader, Set<String>> loaderToPackages = new HashMap<>();
    for (ResolvedModule resolvedModule : cf.modules()) {
        ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
        ClassLoader loader = clf.apply(descriptor.name());
        Set<String> loaderPackages = loaderToPackages.computeIfAbsent(loader, k -> new HashSet<>());
        for (String pkg : descriptor.packages()) {
            boolean added = loaderPackages.add(pkg);
            if (!added) {
                throw fail("More than one module with package %s mapped" + " to the same class loader", pkg);
            }
        }
    }
}
Also used : ModuleDescriptor(java.lang.module.ModuleDescriptor) Set(java.util.Set) HashSet(java.util.HashSet) ResolvedModule(java.lang.module.ResolvedModule) HashMap(java.util.HashMap)

Example 4 with ModuleDescriptor

use of java.lang.module.ModuleDescriptor in project Bytecoder by mirkosertic.

the class ModuleBootstrap method addIllegalAccess.

/**
 * Process the --illegal-access option (and its default) to open packages
 * of system modules in the boot layer to code in unnamed modules.
 */
private static void addIllegalAccess(ModuleFinder upgradeModulePath, SystemModules systemModules, ModuleLayer bootLayer, boolean extraExportsOrOpens) {
    String value = getAndRemoveProperty("jdk.module.illegalAccess");
    IllegalAccessLogger.Mode mode = IllegalAccessLogger.Mode.ONESHOT;
    if (value != null) {
        switch(value) {
            case "deny":
                return;
            case "permit":
                break;
            case "warn":
                mode = IllegalAccessLogger.Mode.WARN;
                break;
            case "debug":
                mode = IllegalAccessLogger.Mode.DEBUG;
                break;
            default:
                fail("Value specified to --illegal-access not recognized:" + " '" + value + "'");
                return;
        }
    }
    IllegalAccessLogger.Builder builder = new IllegalAccessLogger.Builder(mode, System.err);
    Map<String, Set<String>> map1 = systemModules.concealedPackagesToOpen();
    Map<String, Set<String>> map2 = systemModules.exportedPackagesToOpen();
    if (map1.isEmpty() && map2.isEmpty()) {
        // need to generate (exploded build)
        IllegalAccessMaps maps = IllegalAccessMaps.generate(limitedFinder());
        map1 = maps.concealedPackagesToOpen();
        map2 = maps.exportedPackagesToOpen();
    }
    // open specific packages in the system modules
    for (Module m : bootLayer.modules()) {
        ModuleDescriptor descriptor = m.getDescriptor();
        String name = m.getName();
        // skip open modules
        if (descriptor.isOpen()) {
            continue;
        }
        // skip modules loaded from the upgrade module path
        if (upgradeModulePath != null && upgradeModulePath.find(name).isPresent()) {
            continue;
        }
        Set<String> concealedPackages = map1.getOrDefault(name, Set.of());
        Set<String> exportedPackages = map2.getOrDefault(name, Set.of());
        // refresh the set of concealed and exported packages if needed
        if (extraExportsOrOpens) {
            concealedPackages = new HashSet<>(concealedPackages);
            exportedPackages = new HashSet<>(exportedPackages);
            Iterator<String> iterator = concealedPackages.iterator();
            while (iterator.hasNext()) {
                String pn = iterator.next();
                if (m.isExported(pn, BootLoader.getUnnamedModule())) {
                    // concealed package is exported to ALL-UNNAMED
                    iterator.remove();
                    exportedPackages.add(pn);
                }
            }
            iterator = exportedPackages.iterator();
            while (iterator.hasNext()) {
                String pn = iterator.next();
                if (m.isOpen(pn, BootLoader.getUnnamedModule())) {
                    // exported package is opened to ALL-UNNAMED
                    iterator.remove();
                }
            }
        }
        // log reflective access to all types in concealed packages
        builder.logAccessToConcealedPackages(m, concealedPackages);
        // log reflective access to non-public members/types in exported packages
        builder.logAccessToExportedPackages(m, exportedPackages);
        // open the packages to unnamed modules
        JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
        jla.addOpensToAllUnnamed(m, concat(concealedPackages.iterator(), exportedPackages.iterator()));
    }
    builder.complete();
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) JavaLangAccess(jdk.internal.misc.JavaLangAccess) ModuleDescriptor(java.lang.module.ModuleDescriptor) ResolvedModule(java.lang.module.ResolvedModule)

Example 5 with ModuleDescriptor

use of java.lang.module.ModuleDescriptor in project Bytecoder by mirkosertic.

the class ModuleInfo method doRead.

/**
 * Reads the input as a module-info class file.
 *
 * @throws IOException
 * @throws InvalidModuleDescriptorException
 * @throws IllegalArgumentException if thrown by the ModuleDescriptor.Builder
 *         because an identifier is not a legal Java identifier, duplicate
 *         exports, and many other reasons
 */
private Attributes doRead(DataInput in) throws IOException {
    int magic = in.readInt();
    if (magic != 0xCAFEBABE)
        throw invalidModuleDescriptor("Bad magic number");
    int minor_version = in.readUnsignedShort();
    int major_version = in.readUnsignedShort();
    if (major_version < 53) {
        throw invalidModuleDescriptor("Must be >= 53.0");
    }
    ConstantPool cpool = new ConstantPool(in);
    int access_flags = in.readUnsignedShort();
    if (access_flags != ACC_MODULE)
        throw invalidModuleDescriptor("access_flags should be ACC_MODULE");
    int this_class = in.readUnsignedShort();
    String mn = cpool.getClassName(this_class);
    if (!"module-info".equals(mn))
        throw invalidModuleDescriptor("this_class should be module-info");
    int super_class = in.readUnsignedShort();
    if (super_class > 0)
        throw invalidModuleDescriptor("bad #super_class");
    int interfaces_count = in.readUnsignedShort();
    if (interfaces_count > 0)
        throw invalidModuleDescriptor("Bad #interfaces");
    int fields_count = in.readUnsignedShort();
    if (fields_count > 0)
        throw invalidModuleDescriptor("Bad #fields");
    int methods_count = in.readUnsignedShort();
    if (methods_count > 0)
        throw invalidModuleDescriptor("Bad #methods");
    int attributes_count = in.readUnsignedShort();
    // the names of the attributes found in the class file
    Set<String> attributes = new HashSet<>();
    Builder builder = null;
    Set<String> allPackages = null;
    String mainClass = null;
    ModuleTarget moduleTarget = null;
    ModuleHashes moduelHashes = null;
    ModuleResolution moduleResolution = null;
    for (int i = 0; i < attributes_count; i++) {
        int name_index = in.readUnsignedShort();
        String attribute_name = cpool.getUtf8(name_index);
        int length = in.readInt();
        boolean added = attributes.add(attribute_name);
        if (!added && isAttributeAtMostOnce(attribute_name)) {
            throw invalidModuleDescriptor("More than one " + attribute_name + " attribute");
        }
        switch(attribute_name) {
            case MODULE:
                builder = readModuleAttribute(in, cpool);
                break;
            case MODULE_PACKAGES:
                allPackages = readModulePackagesAttribute(in, cpool);
                break;
            case MODULE_MAIN_CLASS:
                mainClass = readModuleMainClassAttribute(in, cpool);
                break;
            case MODULE_TARGET:
                moduleTarget = readModuleTargetAttribute(in, cpool);
                break;
            case MODULE_HASHES:
                if (parseHashes) {
                    moduelHashes = readModuleHashesAttribute(in, cpool);
                } else {
                    in.skipBytes(length);
                }
                break;
            case MODULE_RESOLUTION:
                moduleResolution = readModuleResolution(in, cpool);
                break;
            default:
                if (isAttributeDisallowed(attribute_name)) {
                    throw invalidModuleDescriptor(attribute_name + " attribute not allowed");
                } else {
                    in.skipBytes(length);
                }
        }
    }
    // the Module attribute is required
    if (builder == null) {
        throw invalidModuleDescriptor(MODULE + " attribute not found");
    }
    // ModuleMainClass  attribute
    if (mainClass != null) {
        builder.mainClass(mainClass);
    }
    // If the ModulePackages attribute is not present then the packageFinder
    // is used to find the set of packages
    boolean usedPackageFinder = false;
    if (allPackages == null && packageFinder != null) {
        try {
            allPackages = packageFinder.get();
        } catch (UncheckedIOException x) {
            throw x.getCause();
        }
        usedPackageFinder = true;
    }
    if (allPackages != null) {
        Set<String> knownPackages = JLMA.packages(builder);
        if (!allPackages.containsAll(knownPackages)) {
            Set<String> missingPackages = new HashSet<>(knownPackages);
            missingPackages.removeAll(allPackages);
            assert !missingPackages.isEmpty();
            String missingPackage = missingPackages.iterator().next();
            String tail;
            if (usedPackageFinder) {
                tail = " not found in module";
            } else {
                tail = " missing from ModulePackages class file attribute";
            }
            throw invalidModuleDescriptor("Package " + missingPackage + tail);
        }
        builder.packages(allPackages);
    }
    ModuleDescriptor descriptor = builder.build();
    return new Attributes(descriptor, moduleTarget, moduelHashes, moduleResolution);
}
Also used : Builder(java.lang.module.ModuleDescriptor.Builder) UncheckedIOException(java.io.UncheckedIOException) ModuleDescriptor(java.lang.module.ModuleDescriptor) HashSet(java.util.HashSet)

Aggregations

ModuleDescriptor (java.lang.module.ModuleDescriptor)21 HashMap (java.util.HashMap)13 HashSet (java.util.HashSet)12 ModuleReference (java.lang.module.ModuleReference)10 Set (java.util.Set)10 ResolvedModule (java.lang.module.ResolvedModule)9 Map (java.util.Map)9 URI (java.net.URI)8 ArrayList (java.util.ArrayList)7 File (java.io.File)6 IOException (java.io.IOException)6 Collections (java.util.Collections)6 List (java.util.List)6 Optional (java.util.Optional)6 JarFile (java.util.jar.JarFile)6 UncheckedIOException (java.io.UncheckedIOException)5 ModuleFinder (java.lang.module.ModuleFinder)5 Path (java.nio.file.Path)5 Paths (java.nio.file.Paths)5 Collectors (java.util.stream.Collectors)5