< prev index next > src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java
Print this page
/*
- * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReader;
import java.lang.module.ModuleReference;
import java.lang.reflect.Constructor;
import java.net.URI;
- import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
- import jdk.internal.jimage.ImageLocation;
import jdk.internal.jimage.ImageReader;
import jdk.internal.jimage.ImageReaderFactory;
import jdk.internal.access.JavaNetUriAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.util.StaticProperty;
throw new InternalError("Unable to detect the run-time image");
return ModulePath.of(ModuleBootstrap.patcher(), dir);
}
/**
- * Parses the module-info.class of all module in the runtime image and
+ * Parses the {@code module-info.class} of all modules in the runtime image and
* returns a ModuleFinder to find the modules.
*
* @apiNote The returned ModuleFinder is thread safe.
*/
private static ModuleFinder ofModuleInfos() {
// parse the module-info.class in every module
Map<String, ModuleInfo.Attributes> nameToAttributes = new HashMap<>();
Map<String, byte[]> nameToHash = new HashMap<>();
- ImageReader reader = SystemImage.reader();
- for (String mn : reader.getModuleNames()) {
- ImageLocation loc = reader.findLocation(mn, "module-info.class");
- ModuleInfo.Attributes attrs
- = ModuleInfo.read(reader.getResourceBuffer(loc), null);
- nameToAttributes.put(mn, attrs);
+ allModuleAttributes().forEach(attrs -> {
+ nameToAttributes.put(attrs.descriptor().name(), attrs);
ModuleHashes hashes = attrs.recordedHashes();
if (hashes != null) {
for (String name : hashes.names()) {
nameToHash.computeIfAbsent(name, k -> hashes.hashFor(name));
}
}
- }
+ });
// create a ModuleReference for each module
Set<ModuleReference> mrefs = new HashSet<>();
Map<String, ModuleReference> nameToModule = new HashMap<>();
for (Map.Entry<String, ModuleInfo.Attributes> e : nameToAttributes.entrySet()) {
}
return new SystemModuleFinder(mrefs, nameToModule);
}
+ /**
+ * Parses the {@code module-info.class} of all modules in the runtime image and
+ * returns a stream of {@link ModuleInfo.Attributes Attributes} for them. The
+ * returned attributes are in no specific order.
+ */
+ private static Stream<ModuleInfo.Attributes> allModuleAttributes() {
+ // System-wide image reader.
+ ImageReader reader = SystemImage.reader();
+ try {
+ return reader.findNode("/modules")
+ .getChildNames()
+ .map(mn -> readModuleAttributes(reader, mn));
+ } catch (IOException e) {
+ throw new Error("Error reading root /modules entry", e);
+ }
+ }
+
+ /**
+ * Returns the module's "module-info", returning a holder for its class file
+ * attributes. Every module is required to have a valid {@code module-info.class}.
+ */
+ private static ModuleInfo.Attributes readModuleAttributes(ImageReader reader, String moduleName) {
+ Exception err = null;
+ try {
+ ImageReader.Node node = reader.findNode(moduleName + "/module-info.class");
+ if (node != null && node.isResource()) {
+ return ModuleInfo.read(reader.getResourceBuffer(node), null);
+ }
+ } catch (IOException | UncheckedIOException e) {
+ err = e;
+ }
+ throw new Error("Missing or invalid module-info.class for module: " + moduleName, err);
+ }
+
/**
* A ModuleFinder that finds module in an array or set of modules.
*/
private static class SystemModuleFinder implements ModuleFinder {
final Set<ModuleReference> mrefs;
SystemModuleReader(String module) {
this.module = module;
}
- /**
- * Returns the ImageLocation for the given resource, {@code null}
- * if not found.
- */
- private ImageLocation findImageLocation(String name) throws IOException {
- Objects.requireNonNull(name);
- if (closed)
- throw new IOException("ModuleReader is closed");
- ImageReader imageReader = SystemImage.reader();
- if (imageReader != null) {
- return imageReader.findLocation(module, name);
- } else {
- // not an images build
- return null;
- }
- }
-
/**
* Returns {@code true} if the given resource exists, {@code false}
* if not found.
*/
- private boolean containsImageLocation(String name) throws IOException {
- Objects.requireNonNull(name);
+ private boolean containsResource(String resourcePath) throws IOException {
+ Objects.requireNonNull(resourcePath);
if (closed)
throw new IOException("ModuleReader is closed");
ImageReader imageReader = SystemImage.reader();
if (imageReader != null) {
- return imageReader.verifyLocation(module, name);
+ ImageReader.Node node = imageReader.findNode("/modules" + resourcePath);
+ return node != null && node.isResource();
} else {
// not an images build
return false;
}
}
@Override
public Optional<URI> find(String name) throws IOException {
- if (containsImageLocation(name)) {
- URI u = JNUA.create("jrt", "/" + module + "/" + name);
+ String resourcePath = "/" + module + "/" + name;
+ if (containsResource(resourcePath)) {
+ URI u = JNUA.create("jrt", resourcePath);
return Optional.of(u);
} else {
return Optional.empty();
}
}
} finally {
release(bb);
}
}
+ /**
+ * Returns the node for the given resource if found. If the name references
+ * a non-resource node, then {@code null} is returned.
+ */
+ private ImageReader.Node findResource(ImageReader reader, String name) throws IOException {
+ Objects.requireNonNull(name);
+ if (closed) {
+ throw new IOException("ModuleReader is closed");
+ }
+ String nodeName = "/modules/" + module + "/" + name;
+ ImageReader.Node node = reader.findNode(nodeName);
+ return (node != null && node.isResource()) ? node : null;
+ }
+
@Override
public Optional<ByteBuffer> read(String name) throws IOException {
- ImageLocation location = findImageLocation(name);
- if (location != null) {
- return Optional.of(SystemImage.reader().getResourceBuffer(location));
- } else {
- return Optional.empty();
- }
+ ImageReader reader = SystemImage.reader();
+ return Optional.ofNullable(findResource(reader, name))
+ .map(reader::getResourceBuffer);
}
@Override
public void release(ByteBuffer bb) {
Objects.requireNonNull(bb);
* run-time image.
*/
private static class ModuleContentSpliterator implements Spliterator<String> {
final String moduleRoot;
final Deque<ImageReader.Node> stack;
- Iterator<ImageReader.Node> iterator;
+ Iterator<String> iterator;
ModuleContentSpliterator(String module) throws IOException {
moduleRoot = "/modules/" + module;
stack = new ArrayDeque<>();
* there are no remaining nodes to visit.
*/
private String next() throws IOException {
for (;;) {
while (iterator.hasNext()) {
- ImageReader.Node node = iterator.next();
- String name = node.getName();
+ String name = iterator.next();
+ ImageReader.Node node = SystemImage.reader().findNode(name);
if (node.isDirectory()) {
- // build node
- ImageReader.Node dir = SystemImage.reader().findNode(name);
- assert dir.isDirectory();
- stack.push(dir);
+ stack.push(node);
} else {
// strip /modules/$MODULE/ prefix
return name.substring(moduleRoot.length() + 1);
}
}
if (stack.isEmpty()) {
return null;
} else {
ImageReader.Node dir = stack.poll();
assert dir.isDirectory();
- iterator = dir.getChildren().iterator();
+ iterator = dir.getChildNames().iterator();
}
}
}
@Override
< prev index next >