< prev index next >
src/java.base/share/classes/jdk/internal/module/SystemModuleFinder.java
Print this page
@@ -21,24 +21,27 @@
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-package java.lang.module;
+package jdk.internal.module;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
import java.net.URI;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
@@ -52,26 +55,22 @@
import jdk.internal.jimage.ImageLocation;
import jdk.internal.jimage.ImageReader;
import jdk.internal.jimage.ImageReaderFactory;
import jdk.internal.misc.JavaNetUriAccess;
import jdk.internal.misc.SharedSecrets;
-import jdk.internal.module.ModuleBootstrap;
-import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleHashes.HashSupplier;
-import jdk.internal.module.SystemModules;
-import jdk.internal.module.ModulePatcher;
import jdk.internal.perf.PerfCounter;
/**
* A {@code ModuleFinder} that finds modules that are linked into the
* run-time image.
*
* The modules linked into the run-time image are assumed to have the
* Packages attribute.
*/
-class SystemModuleFinder implements ModuleFinder {
+public class SystemModuleFinder implements ModuleFinder {
private static final JavaNetUriAccess JNUA = SharedSecrets.getJavaNetUriAccess();
private static final PerfCounter initTime
= PerfCounter.newPerfCounter("jdk.module.finder.jimage.initTime");
@@ -82,90 +81,30 @@
private static final PerfCounter exportsCount
= PerfCounter.newPerfCounter("jdk.module.finder.jimage.exports");
// ImageReader used to access all modules in the image
private static final ImageReader imageReader;
- // the set of modules in the run-time image
- private static final Set<ModuleReference> modules;
+ // singleton finder to find modules in the run-time images
+ private static final SystemModuleFinder INSTANCE;
- // maps module name to module reference
- private static final Map<String, ModuleReference> nameToModule;
+ public static SystemModuleFinder getInstance() {
+ return INSTANCE;
+ }
/**
* For now, the module references are created eagerly on the assumption
* that service binding will require all modules to be located.
*/
static {
long t0 = System.nanoTime();
imageReader = ImageReaderFactory.getImageReader();
- String[] names = moduleNames();
- ModuleDescriptor[] descriptors = descriptors(names);
-
- int n = names.length;
- moduleCount.add(n);
-
- ModuleReference[] mods = new ModuleReference[n];
-
- @SuppressWarnings(value = {"rawtypes", "unchecked"})
- Entry<String, ModuleReference>[] map
- = (Entry<String, ModuleReference>[])new Entry[n];
-
- for (int i = 0; i < n; i++) {
- ModuleDescriptor md = descriptors[i];
-
- // create the ModuleReference
- ModuleReference mref = toModuleReference(md, hashSupplier(i, names[i]));
-
- mods[i] = mref;
- map[i] = Map.entry(names[i], mref);
-
- // counters
- packageCount.add(md.packages().size());
- exportsCount.add(md.exports().size());
- }
-
- modules = Set.of(mods);
- nameToModule = Map.ofEntries(map);
+ INSTANCE = new SystemModuleFinder();
initTime.addElapsedTimeFrom(t0);
}
- /*
- * Returns an array of ModuleDescriptor of the given module names.
- *
- * This obtains ModuleDescriptors from SystemModules class that is generated
- * from the jlink system-modules plugin. ModuleDescriptors have already
- * been validated at link time.
- *
- * If java.base is patched, or fastpath is disabled for troubleshooting
- * purpose, it will fall back to find system modules via jrt file system.
- */
- private static ModuleDescriptor[] descriptors(String[] names) {
- // fastpath is enabled by default.
- // It can be disabled for troubleshooting purpose.
- boolean disabled =
- System.getProperty("jdk.system.module.finder.disabledFastPath") != null;
-
- // fast loading of ModuleDescriptor of system modules
- if (isFastPathSupported() && !disabled)
- return SystemModules.modules();
-
- // if fast loading of ModuleDescriptors is disabled
- // fallback to read module-info.class
- ModuleDescriptor[] descriptors = new ModuleDescriptor[names.length];
- for (int i = 0; i < names.length; i++) {
- String mn = names[i];
- ImageLocation loc = imageReader.findLocation(mn, "module-info.class");
- descriptors[i] = ModuleDescriptor.read(imageReader.getResourceBuffer(loc));
-
- // add the recorded hashes of tied modules
- Hashes.add(descriptors[i]);
- }
- return descriptors;
- }
-
private static boolean isFastPathSupported() {
return SystemModules.MODULE_NAMES.length > 0;
}
private static String[] moduleNames() {
@@ -176,60 +115,24 @@
// this happens when java.base is patched with java.base
// from an exploded image
return imageReader.getModuleNames();
}
- private static ModuleReference toModuleReference(ModuleDescriptor md,
- HashSupplier hash)
- {
- String mn = md.name();
- URI uri = JNUA.create("jrt", "/".concat(mn));
-
- Supplier<ModuleReader> readerSupplier = new Supplier<>() {
- @Override
- public ModuleReader get() {
- return new ImageModuleReader(mn, uri);
- }
- };
-
- ModuleReference mref =
- new ModuleReference(md, uri, readerSupplier, hash);
-
- // may need a reference to a patched module if --patch-module specified
- mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
-
- return mref;
- }
-
- private static HashSupplier hashSupplier(int index, String name) {
- if (isFastPathSupported()) {
- return new HashSupplier() {
- @Override
- public byte[] generate(String algorithm) {
- return SystemModules.MODULES_TO_HASH[index];
- }
- };
- } else {
- return Hashes.hashFor(name);
- }
- }
- /*
- * This helper class is only used when SystemModules is patched.
- * It will get the recorded hashes from module-info.class.
+ /**
+ * Helper class to use the recorded hashes to create a HashSupplier
*/
private static class Hashes {
static Map<String, byte[]> hashes = new HashMap<>();
- static void add(ModuleDescriptor descriptor) {
- Optional<ModuleHashes> ohashes = descriptor.hashes();
- if (ohashes.isPresent()) {
- hashes.putAll(ohashes.get().hashes());
+ static void add(ModuleHashes recordedHashes) {
+ if (recordedHashes != null) {
+ hashes.putAll(recordedHashes.hashes());
}
}
- static HashSupplier hashFor(String name) {
+ static HashSupplier hashSupplierFor(String name) {
if (!hashes.containsKey(name))
return null;
return new HashSupplier() {
@Override
@@ -238,11 +141,82 @@
}
};
}
}
- SystemModuleFinder() { }
+ // the set of modules in the run-time image
+ private final Set<ModuleReference> modules;
+
+ // maps module name to module reference
+ private final Map<String, ModuleReference> nameToModule;
+
+ private SystemModuleFinder() {
+ String[] names = moduleNames();
+ int n = names.length;
+ moduleCount.add(n);
+
+ // fastpath is enabled by default.
+ // It can be disabled for troubleshooting purpose.
+ boolean disabled =
+ System.getProperty("jdk.system.module.finder.disabledFastPath") != null;
+
+ ModuleDescriptor[] descriptors;
+ ModuleHashes[] recordedHashes;
+ ModuleResolution[] moduleResolutions;
+
+ // fast loading of ModuleDescriptor of system modules
+ if (isFastPathSupported() && !disabled) {
+ descriptors = SystemModules.descriptors();
+ recordedHashes = SystemModules.hashes();
+ moduleResolutions = SystemModules.moduleResolutions();
+ } else {
+ // if fast loading of ModuleDescriptors is disabled
+ // fallback to read module-info.class
+ descriptors = new ModuleDescriptor[n];
+ recordedHashes = new ModuleHashes[n];
+ moduleResolutions = new ModuleResolution[n];
+ for (int i = 0; i < names.length; i++) {
+ String mn = names[i];
+ ImageLocation loc = imageReader.findLocation(mn, "module-info.class");
+ ModuleInfo.Attributes attrs =
+ ModuleInfo.read(imageReader.getResourceBuffer(loc), null);
+ descriptors[i] = attrs.descriptor();
+ recordedHashes[i] = attrs.recordedHashes();
+ moduleResolutions[i] = attrs.moduleResolution();
+ }
+ }
+
+ // record the hashes to build HashSupplier
+ for (ModuleHashes mh : recordedHashes) {
+ Hashes.add(mh);
+ }
+
+ ModuleReference[] mods = new ModuleReference[n];
+
+ @SuppressWarnings(value = {"rawtypes", "unchecked"})
+ Entry<String, ModuleReference>[] map
+ = (Entry<String, ModuleReference>[])new Entry[n];
+
+ for (int i = 0; i < n; i++) {
+ ModuleDescriptor md = descriptors[i];
+
+ // create the ModuleReference
+ ModuleReference mref = toModuleReference(md,
+ recordedHashes[i],
+ Hashes.hashSupplierFor(names[i]),
+ moduleResolutions[i]);
+ mods[i] = mref;
+ map[i] = Map.entry(names[i], mref);
+
+ // counters
+ packageCount.add(md.packages().size());
+ exportsCount.add(md.exports().size());
+ }
+
+ modules = Set.of(mods);
+ nameToModule = Map.ofEntries(map);
+ }
@Override
public Optional<ModuleReference> find(String name) {
Objects.requireNonNull(name);
return Optional.ofNullable(nameToModule.get(name));
@@ -251,10 +225,34 @@
@Override
public Set<ModuleReference> findAll() {
return modules;
}
+ private ModuleReference toModuleReference(ModuleDescriptor md,
+ ModuleHashes recordedHashes,
+ HashSupplier hasher,
+ ModuleResolution mres) {
+ String mn = md.name();
+ URI uri = JNUA.create("jrt", "/".concat(mn));
+
+ Supplier<ModuleReader> readerSupplier = new Supplier<>() {
+ @Override
+ public ModuleReader get() {
+ return new ImageModuleReader(mn, uri);
+ }
+ };
+
+ ModuleReference mref =
+ new ModuleReferenceImpl(md, uri, readerSupplier, null,
+ recordedHashes, hasher, mres);
+
+ // may need a reference to a patched module if --patch-module specified
+ mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
+
+ return mref;
+ }
+
/**
* A ModuleReader for reading resources from a module linked into the
* run-time image.
*/
< prev index next >