< prev index next >

src/java.base/share/classes/jdk/internal/module/SystemModuleFinder.java

Print this page




   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.module;
  27 
  28 import java.io.ByteArrayInputStream;
  29 import java.io.IOException;
  30 import java.io.InputStream;
  31 import java.io.UncheckedIOException;




  32 import java.net.URI;
  33 import java.net.URLConnection;
  34 import java.nio.ByteBuffer;
  35 import java.util.ArrayDeque;
  36 import java.util.Collections;
  37 import java.util.Deque;
  38 import java.util.HashMap;
  39 import java.util.HashSet;
  40 import java.util.Iterator;
  41 import java.util.Map;
  42 import java.util.Map.Entry;
  43 import java.util.Objects;
  44 import java.util.Optional;
  45 import java.util.Set;
  46 import java.util.Spliterator;
  47 import java.util.function.Consumer;
  48 import java.util.function.Supplier;
  49 import java.util.stream.Stream;
  50 import java.util.stream.StreamSupport;
  51 
  52 import jdk.internal.jimage.ImageLocation;
  53 import jdk.internal.jimage.ImageReader;
  54 import jdk.internal.jimage.ImageReaderFactory;
  55 import jdk.internal.misc.JavaNetUriAccess;
  56 import jdk.internal.misc.SharedSecrets;
  57 import jdk.internal.module.ModuleBootstrap;
  58 import jdk.internal.module.ModuleHashes;
  59 import jdk.internal.module.ModuleHashes.HashSupplier;
  60 import jdk.internal.module.SystemModules;
  61 import jdk.internal.module.ModulePatcher;
  62 import jdk.internal.perf.PerfCounter;
  63 
  64 /**
  65  * A {@code ModuleFinder} that finds modules that are linked into the
  66  * run-time image.
  67  *
  68  * The modules linked into the run-time image are assumed to have the
  69  * Packages attribute.
  70  */
  71 
  72 class SystemModuleFinder implements ModuleFinder {
  73 
  74     private static final JavaNetUriAccess JNUA = SharedSecrets.getJavaNetUriAccess();
  75 
  76     private static final PerfCounter initTime
  77         = PerfCounter.newPerfCounter("jdk.module.finder.jimage.initTime");
  78     private static final PerfCounter moduleCount
  79         = PerfCounter.newPerfCounter("jdk.module.finder.jimage.modules");
  80     private static final PerfCounter packageCount
  81         = PerfCounter.newPerfCounter("jdk.module.finder.jimage.packages");
  82     private static final PerfCounter exportsCount
  83         = PerfCounter.newPerfCounter("jdk.module.finder.jimage.exports");
  84     // ImageReader used to access all modules in the image
  85     private static final ImageReader imageReader;
  86 
  87     // the set of modules in the run-time image
  88     private static final Set<ModuleReference> modules;
  89 
  90     // maps module name to module reference
  91     private static final Map<String, ModuleReference> nameToModule;

  92 
  93     /**
  94      * For now, the module references are created eagerly on the assumption
  95      * that service binding will require all modules to be located.
  96      */
  97     static {
  98         long t0 = System.nanoTime();
  99         imageReader = ImageReaderFactory.getImageReader();
 100 
 101         String[] names = moduleNames();
 102         ModuleDescriptor[] descriptors = descriptors(names);
 103 
 104         int n = names.length;
 105         moduleCount.add(n);
 106 
 107         ModuleReference[] mods = new ModuleReference[n];
 108 
 109         @SuppressWarnings(value = {"rawtypes", "unchecked"})
 110         Entry<String, ModuleReference>[] map
 111             = (Entry<String, ModuleReference>[])new Entry[n];
 112 
 113         for (int i = 0; i < n; i++) {
 114             ModuleDescriptor md = descriptors[i];
 115 
 116             // create the ModuleReference
 117             ModuleReference mref = toModuleReference(md, hashSupplier(i, names[i]));
 118 
 119             mods[i] = mref;
 120             map[i] = Map.entry(names[i], mref);
 121 
 122             // counters
 123             packageCount.add(md.packages().size());
 124             exportsCount.add(md.exports().size());
 125         }
 126 
 127         modules = Set.of(mods);
 128         nameToModule = Map.ofEntries(map);
 129 
 130         initTime.addElapsedTimeFrom(t0);
 131     }
 132 
 133     /*
 134      * Returns an array of ModuleDescriptor of the given module names.
 135      *
 136      * This obtains ModuleDescriptors from SystemModules class that is generated
 137      * from the jlink system-modules plugin.  ModuleDescriptors have already
 138      * been validated at link time.
 139      *
 140      * If java.base is patched, or fastpath is disabled for troubleshooting
 141      * purpose, it will fall back to find system modules via jrt file system.
 142      */
 143     private static ModuleDescriptor[] descriptors(String[] names) {
 144         // fastpath is enabled by default.
 145         // It can be disabled for troubleshooting purpose.
 146         boolean disabled =
 147             System.getProperty("jdk.system.module.finder.disabledFastPath") != null;
 148 
 149         // fast loading of ModuleDescriptor of system modules
 150         if (isFastPathSupported() && !disabled)
 151             return SystemModules.modules();
 152 
 153         // if fast loading of ModuleDescriptors is disabled
 154         // fallback to read module-info.class
 155         ModuleDescriptor[] descriptors = new ModuleDescriptor[names.length];
 156         for (int i = 0; i < names.length; i++) {
 157             String mn = names[i];
 158             ImageLocation loc = imageReader.findLocation(mn, "module-info.class");
 159             descriptors[i] = ModuleDescriptor.read(imageReader.getResourceBuffer(loc));
 160 
 161             // add the recorded hashes of tied modules
 162             Hashes.add(descriptors[i]);
 163         }
 164         return descriptors;
 165     }
 166 
 167     private static boolean isFastPathSupported() {
 168        return SystemModules.MODULE_NAMES.length > 0;
 169     }
 170 
 171     private static String[] moduleNames() {
 172         if (isFastPathSupported())
 173             // module names recorded at link time
 174             return SystemModules.MODULE_NAMES;
 175 
 176         // this happens when java.base is patched with java.base
 177         // from an exploded image
 178         return imageReader.getModuleNames();
 179     }
 180 
 181     private static ModuleReference toModuleReference(ModuleDescriptor md,
 182                                                      HashSupplier hash)
 183     {
 184         String mn = md.name();
 185         URI uri = JNUA.create("jrt", "/".concat(mn));
 186 
 187         Supplier<ModuleReader> readerSupplier = new Supplier<>() {
 188             @Override
 189             public ModuleReader get() {
 190                 return new ImageModuleReader(mn, uri);
 191             }
 192         };
 193 
 194         ModuleReference mref =
 195             new ModuleReference(md, uri, readerSupplier, hash);
 196 
 197         // may need a reference to a patched module if --patch-module specified
 198         mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
 199 
 200         return mref;
 201     }
 202 
 203     private static HashSupplier hashSupplier(int index, String name) {
 204         if (isFastPathSupported()) {
 205             return new HashSupplier() {
 206                 @Override
 207                 public byte[] generate(String algorithm) {
 208                     return SystemModules.MODULES_TO_HASH[index];
 209                 }
 210             };
 211         } else {
 212             return Hashes.hashFor(name);
 213         }
 214     }
 215 
 216     /*
 217      * This helper class is only used when SystemModules is patched.
 218      * It will get the recorded hashes from module-info.class.
 219      */
 220     private static class Hashes {
 221         static Map<String, byte[]> hashes = new HashMap<>();
 222 
 223         static void add(ModuleDescriptor descriptor) {
 224             Optional<ModuleHashes> ohashes = descriptor.hashes();
 225             if (ohashes.isPresent()) {
 226                 hashes.putAll(ohashes.get().hashes());
 227             }
 228         }
 229 
 230         static HashSupplier hashFor(String name) {
 231             if (!hashes.containsKey(name))
 232                 return null;
 233 
 234             return new HashSupplier() {
 235                 @Override
 236                 public byte[] generate(String algorithm) {
 237                     return hashes.get(name);
 238                 }
 239             };
 240         }
 241     }
 242 
 243     SystemModuleFinder() { }







































































 244 
 245     @Override
 246     public Optional<ModuleReference> find(String name) {
 247         Objects.requireNonNull(name);
 248         return Optional.ofNullable(nameToModule.get(name));
 249     }
 250 
 251     @Override
 252     public Set<ModuleReference> findAll() {
 253         return modules;
 254     }
 255 
























 256 
 257     /**
 258      * A ModuleReader for reading resources from a module linked into the
 259      * run-time image.
 260      */
 261     static class ImageModuleReader implements ModuleReader {
 262         private final String module;
 263         private volatile boolean closed;
 264 
 265         /**
 266          * If there is a security manager set then check permission to
 267          * connect to the run-time image.
 268          */
 269         private static void checkPermissionToConnect(URI uri) {
 270             SecurityManager sm = System.getSecurityManager();
 271             if (sm != null) {
 272                 try {
 273                     URLConnection uc = uri.toURL().openConnection();
 274                     sm.checkPermission(uc.getPermission());
 275                 } catch (IOException ioe) {




   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.internal.module;
  27 
  28 import java.io.ByteArrayInputStream;
  29 import java.io.IOException;
  30 import java.io.InputStream;
  31 import java.io.UncheckedIOException;
  32 import java.lang.module.ModuleDescriptor;
  33 import java.lang.module.ModuleFinder;
  34 import java.lang.module.ModuleReader;
  35 import java.lang.module.ModuleReference;
  36 import java.net.URI;
  37 import java.net.URLConnection;
  38 import java.nio.ByteBuffer;
  39 import java.util.ArrayDeque;
  40 import java.util.Collections;
  41 import java.util.Deque;
  42 import java.util.HashMap;

  43 import java.util.Iterator;
  44 import java.util.Map;
  45 import java.util.Map.Entry;
  46 import java.util.Objects;
  47 import java.util.Optional;
  48 import java.util.Set;
  49 import java.util.Spliterator;
  50 import java.util.function.Consumer;
  51 import java.util.function.Supplier;
  52 import java.util.stream.Stream;
  53 import java.util.stream.StreamSupport;
  54 
  55 import jdk.internal.jimage.ImageLocation;
  56 import jdk.internal.jimage.ImageReader;
  57 import jdk.internal.jimage.ImageReaderFactory;
  58 import jdk.internal.misc.JavaNetUriAccess;
  59 import jdk.internal.misc.SharedSecrets;


  60 import jdk.internal.module.ModuleHashes.HashSupplier;


  61 import jdk.internal.perf.PerfCounter;
  62 
  63 /**
  64  * A {@code ModuleFinder} that finds modules that are linked into the
  65  * run-time image.
  66  *
  67  * The modules linked into the run-time image are assumed to have the
  68  * Packages attribute.
  69  */
  70 
  71 public class SystemModuleFinder implements ModuleFinder {
  72 
  73     private static final JavaNetUriAccess JNUA = SharedSecrets.getJavaNetUriAccess();
  74 
  75     private static final PerfCounter initTime
  76         = PerfCounter.newPerfCounter("jdk.module.finder.jimage.initTime");
  77     private static final PerfCounter moduleCount
  78         = PerfCounter.newPerfCounter("jdk.module.finder.jimage.modules");
  79     private static final PerfCounter packageCount
  80         = PerfCounter.newPerfCounter("jdk.module.finder.jimage.packages");
  81     private static final PerfCounter exportsCount
  82         = PerfCounter.newPerfCounter("jdk.module.finder.jimage.exports");
  83     // ImageReader used to access all modules in the image
  84     private static final ImageReader imageReader;
  85 
  86     // singleton finder to find modules in the run-time images
  87     private static final SystemModuleFinder INSTANCE;
  88 
  89     public static SystemModuleFinder getInstance() {
  90         return INSTANCE;
  91     }
  92 
  93     /**
  94      * For now, the module references are created eagerly on the assumption
  95      * that service binding will require all modules to be located.
  96      */
  97     static {
  98         long t0 = System.nanoTime();
  99         imageReader = ImageReaderFactory.getImageReader();
 100 
 101         INSTANCE = new SystemModuleFinder();



























 102 
 103         initTime.addElapsedTimeFrom(t0);
 104     }
 105 


































 106     private static boolean isFastPathSupported() {
 107        return SystemModules.MODULE_NAMES.length > 0;
 108     }
 109 
 110     private static String[] moduleNames() {
 111         if (isFastPathSupported())
 112             // module names recorded at link time
 113             return SystemModules.MODULE_NAMES;
 114 
 115         // this happens when java.base is patched with java.base
 116         // from an exploded image
 117         return imageReader.getModuleNames();
 118     }
 119 


































 120 
 121     /**
 122      * Helper class to use the recorded hashes to create a HashSupplier

 123      */
 124     private static class Hashes {
 125         static Map<String, byte[]> hashes = new HashMap<>();
 126 
 127         static void add(ModuleHashes recordedHashes) {
 128             if (recordedHashes != null) {
 129                 hashes.putAll(recordedHashes.hashes());

 130             }
 131         }
 132 
 133         static HashSupplier hashSupplierFor(String name) {
 134             if (!hashes.containsKey(name))
 135                 return null;
 136 
 137             return new HashSupplier() {
 138                 @Override
 139                 public byte[] generate(String algorithm) {
 140                     return hashes.get(name);
 141                 }
 142             };
 143         }
 144     }
 145 
 146     // the set of modules in the run-time image
 147     private final Set<ModuleReference> modules;
 148 
 149     // maps module name to module reference
 150     private final Map<String, ModuleReference> nameToModule;
 151 
 152     private SystemModuleFinder() {
 153         String[] names = moduleNames();
 154         int n = names.length;
 155         moduleCount.add(n);
 156 
 157         // fastpath is enabled by default.
 158         // It can be disabled for troubleshooting purpose.
 159         boolean disabled =
 160             System.getProperty("jdk.system.module.finder.disabledFastPath") != null;
 161 
 162         ModuleDescriptor[] descriptors;
 163         ModuleHashes[] recordedHashes;
 164         ModuleResolution[] moduleResolutions;
 165 
 166         // fast loading of ModuleDescriptor of system modules
 167         if (isFastPathSupported() && !disabled) {
 168             descriptors = SystemModules.descriptors();
 169             recordedHashes = SystemModules.hashes();
 170             moduleResolutions = SystemModules.moduleResolutions();
 171         } else {
 172             // if fast loading of ModuleDescriptors is disabled
 173             // fallback to read module-info.class
 174             descriptors = new ModuleDescriptor[n];
 175             recordedHashes = new ModuleHashes[n];
 176             moduleResolutions = new ModuleResolution[n];
 177             for (int i = 0; i < names.length; i++) {
 178                 String mn = names[i];
 179                 ImageLocation loc = imageReader.findLocation(mn, "module-info.class");
 180                 ModuleInfo.Attributes attrs =
 181                     ModuleInfo.read(imageReader.getResourceBuffer(loc), null);
 182                 descriptors[i] = attrs.descriptor();
 183                 recordedHashes[i] = attrs.recordedHashes();
 184                 moduleResolutions[i] = attrs.moduleResolution();
 185             }
 186         }
 187 
 188         // record the hashes to build HashSupplier
 189         for (ModuleHashes mh : recordedHashes) {
 190             Hashes.add(mh);
 191         }
 192 
 193         ModuleReference[] mods = new ModuleReference[n];
 194 
 195         @SuppressWarnings(value = {"rawtypes", "unchecked"})
 196         Entry<String, ModuleReference>[] map
 197             = (Entry<String, ModuleReference>[])new Entry[n];
 198 
 199         for (int i = 0; i < n; i++) {
 200             ModuleDescriptor md = descriptors[i];
 201 
 202             // create the ModuleReference
 203             ModuleReference mref = toModuleReference(md,
 204                                                      recordedHashes[i],
 205                                                      Hashes.hashSupplierFor(names[i]),
 206                                                      moduleResolutions[i]);
 207             mods[i] = mref;
 208             map[i] = Map.entry(names[i], mref);
 209 
 210             // counters
 211             packageCount.add(md.packages().size());
 212             exportsCount.add(md.exports().size());
 213         }
 214 
 215         modules = Set.of(mods);
 216         nameToModule = Map.ofEntries(map);
 217     }
 218 
 219     @Override
 220     public Optional<ModuleReference> find(String name) {
 221         Objects.requireNonNull(name);
 222         return Optional.ofNullable(nameToModule.get(name));
 223     }
 224 
 225     @Override
 226     public Set<ModuleReference> findAll() {
 227         return modules;
 228     }
 229 
 230     private ModuleReference toModuleReference(ModuleDescriptor md,
 231                                               ModuleHashes recordedHashes,
 232                                               HashSupplier hasher,
 233                                               ModuleResolution mres) {
 234         String mn = md.name();
 235         URI uri = JNUA.create("jrt", "/".concat(mn));
 236 
 237         Supplier<ModuleReader> readerSupplier = new Supplier<>() {
 238             @Override
 239             public ModuleReader get() {
 240                 return new ImageModuleReader(mn, uri);
 241             }
 242         };
 243 
 244         ModuleReference mref =
 245             new ModuleReferenceImpl(md, uri, readerSupplier, null,
 246                                     recordedHashes, hasher, mres);
 247 
 248         // may need a reference to a patched module if --patch-module specified
 249         mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
 250 
 251         return mref;
 252     }
 253 
 254 
 255     /**
 256      * A ModuleReader for reading resources from a module linked into the
 257      * run-time image.
 258      */
 259     static class ImageModuleReader implements ModuleReader {
 260         private final String module;
 261         private volatile boolean closed;
 262 
 263         /**
 264          * If there is a security manager set then check permission to
 265          * connect to the run-time image.
 266          */
 267         private static void checkPermissionToConnect(URI uri) {
 268             SecurityManager sm = System.getSecurityManager();
 269             if (sm != null) {
 270                 try {
 271                     URLConnection uc = uri.toURL().openConnection();
 272                     sm.checkPermission(uc.getPermission());
 273                 } catch (IOException ioe) {


< prev index next >