Path: blob/master/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java
41159 views
/*1* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package jdk.internal.loader;2627import java.io.IOException;28import java.io.InputStream;29import java.lang.module.ModuleDescriptor;30import java.lang.module.ModuleReference;31import java.lang.module.ModuleReader;32import java.lang.ref.SoftReference;33import java.net.MalformedURLException;34import java.net.URI;35import java.net.URL;36import java.nio.ByteBuffer;37import java.security.AccessController;38import java.security.CodeSigner;39import java.security.CodeSource;40import java.security.PermissionCollection;41import java.security.PrivilegedAction;42import java.security.PrivilegedActionException;43import java.security.PrivilegedExceptionAction;44import java.security.SecureClassLoader;45import java.util.ArrayList;46import java.util.Collections;47import java.util.Enumeration;48import java.util.Iterator;49import java.util.List;50import java.util.Map;51import java.util.NoSuchElementException;52import java.util.Optional;53import java.util.concurrent.ConcurrentHashMap;54import java.util.function.Function;55import java.util.jar.Attributes;56import java.util.jar.Manifest;57import java.util.stream.Stream;5859import jdk.internal.access.SharedSecrets;60import jdk.internal.misc.VM;61import jdk.internal.module.ModulePatcher.PatchedModuleReader;62import jdk.internal.module.Resources;63import jdk.internal.vm.annotation.Stable;64import sun.security.util.LazyCodeSourcePermissionCollection;656667/**68* The platform or application class loader. Resources loaded from modules69* defined to the boot class loader are also loaded via an instance of this70* ClassLoader type.71*72* <p> This ClassLoader supports loading of classes and resources from modules.73* Modules are defined to the ClassLoader by invoking the {@link #loadModule}74* method. Defining a module to this ClassLoader has the effect of making the75* types in the module visible. </p>76*77* <p> This ClassLoader also supports loading of classes and resources from a78* class path of URLs that are specified to the ClassLoader at construction79* time. The class path may expand at runtime (the Class-Path attribute in JAR80* files or via instrumentation agents). </p>81*82* <p> The delegation model used by this ClassLoader differs to the regular83* delegation model. When requested to load a class then this ClassLoader first84* maps the class name to its package name. If there is a module defined to a85* BuiltinClassLoader containing this package then the class loader delegates86* directly to that class loader. If there isn't a module containing the87* package then it delegates the search to the parent class loader and if not88* found in the parent then it searches the class path. The main difference89* between this and the usual delegation model is that it allows the platform90* class loader to delegate to the application class loader, important with91* upgraded modules defined to the platform class loader.92*/9394public class BuiltinClassLoader95extends SecureClassLoader96{97static {98if (!ClassLoader.registerAsParallelCapable())99throw new InternalError("Unable to register as parallel capable");100}101102// parent ClassLoader103private final BuiltinClassLoader parent;104105// the URL class path, or null if there is no class path106private @Stable URLClassPath ucp;107108/**109* A module defined/loaded by a built-in class loader.110*111* A LoadedModule encapsulates a ModuleReference along with its CodeSource112* URL to avoid needing to create this URL when defining classes.113*/114private static class LoadedModule {115private final BuiltinClassLoader loader;116private final ModuleReference mref;117private final URI uri; // may be null118private @Stable URL codeSourceURL; // may be null119120LoadedModule(BuiltinClassLoader loader, ModuleReference mref) {121URL url = null;122this.uri = mref.location().orElse(null);123124// for non-jrt schemes we need to resolve the codeSourceURL125// eagerly during bootstrap since the handler might be126// overridden127if (uri != null && !"jrt".equals(uri.getScheme())) {128url = createURL(uri);129}130this.loader = loader;131this.mref = mref;132this.codeSourceURL = url;133}134135BuiltinClassLoader loader() { return loader; }136ModuleReference mref() { return mref; }137String name() { return mref.descriptor().name(); }138139URL codeSourceURL() {140URL url = codeSourceURL;141if (url == null && uri != null) {142codeSourceURL = url = createURL(uri);143}144return url;145}146147private URL createURL(URI uri) {148URL url = null;149try {150url = uri.toURL();151} catch (MalformedURLException | IllegalArgumentException e) {152}153return url;154}155}156157// maps package name to loaded module for modules in the boot layer158private static final Map<String, LoadedModule> packageToModule;159static {160ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get();161if (archivedClassLoaders != null) {162@SuppressWarnings("unchecked")163Map<String, LoadedModule> map164= (Map<String, LoadedModule>) archivedClassLoaders.packageToModule();165packageToModule = map;166} else {167packageToModule = new ConcurrentHashMap<>(1024);168}169}170171/**172* Invoked by ArchivedClassLoaders to archive the package-to-module map.173*/174static Map<String, ?> packageToModule() {175return packageToModule;176}177178// maps a module name to a module reference179private final Map<String, ModuleReference> nameToModule;180181// maps a module reference to a module reader182private final Map<ModuleReference, ModuleReader> moduleToReader;183184// cache of resource name -> list of URLs.185// used only for resources that are not in module packages186private volatile SoftReference<Map<String, List<URL>>> resourceCache;187188/**189* Create a new instance.190*/191BuiltinClassLoader(String name, BuiltinClassLoader parent, URLClassPath ucp) {192// ensure getParent() returns null when the parent is the boot loader193super(name, parent == null || parent == ClassLoaders.bootLoader() ? null : parent);194195this.parent = parent;196this.ucp = ucp;197198this.nameToModule = new ConcurrentHashMap<>(32);199this.moduleToReader = new ConcurrentHashMap<>();200}201202/**203* Appends to the given file path to the class path.204*/205void appendClassPath(String path) {206// assert ucp != null;207ucp.addFile(path);208}209210/**211* Sets the class path, called to reset the class path during -Xshare:dump212*/213void setClassPath(URLClassPath ucp) {214this.ucp = ucp;215}216217/**218* Returns {@code true} if there is a class path associated with this219* class loader.220*/221boolean hasClassPath() {222return ucp != null;223}224225/**226* Register a module this class loader. This has the effect of making the227* types in the module visible.228*/229public void loadModule(ModuleReference mref) {230ModuleDescriptor descriptor = mref.descriptor();231String mn = descriptor.name();232if (nameToModule.putIfAbsent(mn, mref) != null) {233throw new InternalError(mn + " already defined to this loader");234}235236LoadedModule loadedModule = new LoadedModule(this, mref);237for (String pn : descriptor.packages()) {238LoadedModule other = packageToModule.putIfAbsent(pn, loadedModule);239if (other != null) {240throw new InternalError(pn + " in modules " + mn + " and "241+ other.name());242}243}244245// clear resources cache if VM is already initialized246if (resourceCache != null && VM.isModuleSystemInited()) {247resourceCache = null;248}249}250251/**252* Returns the {@code ModuleReference} for the named module defined to253* this class loader; or {@code null} if not defined.254*255* @param name The name of the module to find256*/257protected ModuleReference findModule(String name) {258return nameToModule.get(name);259}260261262// -- finding resources263264/**265* Returns a URL to a resource of the given name in a module defined to266* this class loader.267*/268@Override269public URL findResource(String mn, String name) throws IOException {270URL url = null;271272if (mn != null) {273// find in module274ModuleReference mref = nameToModule.get(mn);275if (mref != null) {276url = findResource(mref, name);277}278} else {279// find on class path280url = findResourceOnClassPath(name);281}282283return checkURL(url); // check access before returning284}285286/**287* Returns an input stream to a resource of the given name in a module288* defined to this class loader.289*/290@SuppressWarnings("removal")291public InputStream findResourceAsStream(String mn, String name)292throws IOException293{294// Need URL to resource when running with a security manager so that295// the right permission check is done.296if (System.getSecurityManager() != null || mn == null) {297URL url = findResource(mn, name);298return (url != null) ? url.openStream() : null;299}300301// find in module defined to this loader, no security manager302ModuleReference mref = nameToModule.get(mn);303if (mref != null) {304return moduleReaderFor(mref).open(name).orElse(null);305} else {306return null;307}308}309310/**311* Finds a resource with the given name in the modules defined to this312* class loader or its class path.313*/314@Override315public URL findResource(String name) {316String pn = Resources.toPackageName(name);317LoadedModule module = packageToModule.get(pn);318if (module != null) {319320// resource is in a package of a module defined to this loader321if (module.loader() == this) {322URL url;323try {324url = findResource(module.name(), name); // checks URL325} catch (IOException ioe) {326return null;327}328if (url != null329&& (name.endsWith(".class")330|| url.toString().endsWith("/")331|| isOpen(module.mref(), pn))) {332return url;333}334}335336} else {337338// not in a module package but may be in module defined to this loader339try {340List<URL> urls = findMiscResource(name);341if (!urls.isEmpty()) {342URL url = urls.get(0);343if (url != null) {344return checkURL(url); // check access before returning345}346}347} catch (IOException ioe) {348return null;349}350351}352353// search class path354URL url = findResourceOnClassPath(name);355return checkURL(url);356}357358/**359* Returns an enumeration of URL objects to all the resources with the360* given name in modules defined to this class loader or on the class361* path of this loader.362*/363@Override364public Enumeration<URL> findResources(String name) throws IOException {365List<URL> checked = new ArrayList<>(); // list of checked URLs366367String pn = Resources.toPackageName(name);368LoadedModule module = packageToModule.get(pn);369if (module != null) {370371// resource is in a package of a module defined to this loader372if (module.loader() == this) {373URL url = findResource(module.name(), name); // checks URL374if (url != null375&& (name.endsWith(".class")376|| url.toString().endsWith("/")377|| isOpen(module.mref(), pn))) {378checked.add(url);379}380}381382} else {383// not in a package of a module defined to this loader384for (URL url : findMiscResource(name)) {385url = checkURL(url);386if (url != null) {387checked.add(url);388}389}390}391392// class path (not checked)393Enumeration<URL> e = findResourcesOnClassPath(name);394395// concat the checked URLs and the (not checked) class path396return new Enumeration<>() {397final Iterator<URL> iterator = checked.iterator();398URL next;399private boolean hasNext() {400if (next != null) {401return true;402} else if (iterator.hasNext()) {403next = iterator.next();404return true;405} else {406// need to check each URL407while (e.hasMoreElements() && next == null) {408next = checkURL(e.nextElement());409}410return next != null;411}412}413@Override414public boolean hasMoreElements() {415return hasNext();416}417@Override418public URL nextElement() {419if (hasNext()) {420URL result = next;421next = null;422return result;423} else {424throw new NoSuchElementException();425}426}427};428429}430431/**432* Returns the list of URLs to a "miscellaneous" resource in modules433* defined to this loader. A miscellaneous resource is not in a module434* package, e.g. META-INF/services/p.S.435*436* The cache used by this method avoids repeated searching of all modules.437*/438@SuppressWarnings("removal")439private List<URL> findMiscResource(String name) throws IOException {440SoftReference<Map<String, List<URL>>> ref = this.resourceCache;441Map<String, List<URL>> map = (ref != null) ? ref.get() : null;442if (map == null) {443// only cache resources after VM is fully initialized444if (VM.isModuleSystemInited()) {445map = new ConcurrentHashMap<>();446this.resourceCache = new SoftReference<>(map);447}448} else {449List<URL> urls = map.get(name);450if (urls != null)451return urls;452}453454// search all modules for the resource455List<URL> urls;456try {457urls = AccessController.doPrivileged(458new PrivilegedExceptionAction<>() {459@Override460public List<URL> run() throws IOException {461List<URL> result = null;462for (ModuleReference mref : nameToModule.values()) {463URI u = moduleReaderFor(mref).find(name).orElse(null);464if (u != null) {465try {466if (result == null)467result = new ArrayList<>();468result.add(u.toURL());469} catch (MalformedURLException |470IllegalArgumentException e) {471}472}473}474return (result != null) ? result : Collections.emptyList();475}476});477} catch (PrivilegedActionException pae) {478throw (IOException) pae.getCause();479}480481// only cache resources after VM is fully initialized482if (map != null) {483map.putIfAbsent(name, urls);484}485486return urls;487}488489/**490* Returns the URL to a resource in a module or {@code null} if not found.491*/492@SuppressWarnings("removal")493private URL findResource(ModuleReference mref, String name) throws IOException {494URI u;495if (System.getSecurityManager() == null) {496u = moduleReaderFor(mref).find(name).orElse(null);497} else {498try {499u = AccessController.doPrivileged(new PrivilegedExceptionAction<> () {500@Override501public URI run() throws IOException {502return moduleReaderFor(mref).find(name).orElse(null);503}504});505} catch (PrivilegedActionException pae) {506throw (IOException) pae.getCause();507}508}509if (u != null) {510try {511return u.toURL();512} catch (MalformedURLException | IllegalArgumentException e) { }513}514return null;515}516517/**518* Returns the URL to a resource in a module. Returns {@code null} if not found519* or an I/O error occurs.520*/521private URL findResourceOrNull(ModuleReference mref, String name) {522try {523return findResource(mref, name);524} catch (IOException ignore) {525return null;526}527}528529/**530* Returns a URL to a resource on the class path.531*/532@SuppressWarnings("removal")533private URL findResourceOnClassPath(String name) {534if (hasClassPath()) {535if (System.getSecurityManager() == null) {536return ucp.findResource(name, false);537} else {538PrivilegedAction<URL> pa = () -> ucp.findResource(name, false);539return AccessController.doPrivileged(pa);540}541} else {542// no class path543return null;544}545}546547/**548* Returns the URLs of all resources of the given name on the class path.549*/550@SuppressWarnings("removal")551private Enumeration<URL> findResourcesOnClassPath(String name) {552if (hasClassPath()) {553if (System.getSecurityManager() == null) {554return ucp.findResources(name, false);555} else {556PrivilegedAction<Enumeration<URL>> pa;557pa = () -> ucp.findResources(name, false);558return AccessController.doPrivileged(pa);559}560} else {561// no class path562return Collections.emptyEnumeration();563}564}565566// -- finding/loading classes567568/**569* Finds the class with the specified binary name.570*/571@Override572protected Class<?> findClass(String cn) throws ClassNotFoundException {573// no class loading until VM is fully initialized574if (!VM.isModuleSystemInited())575throw new ClassNotFoundException(cn);576577// find the candidate module for this class578LoadedModule loadedModule = findLoadedModule(cn);579580Class<?> c = null;581if (loadedModule != null) {582583// attempt to load class in module defined to this loader584if (loadedModule.loader() == this) {585c = findClassInModuleOrNull(loadedModule, cn);586}587588} else {589590// search class path591if (hasClassPath()) {592c = findClassOnClassPathOrNull(cn);593}594595}596597// not found598if (c == null)599throw new ClassNotFoundException(cn);600601return c;602}603604/**605* Finds the class with the specified binary name in a module.606* This method returns {@code null} if the class cannot be found607* or not defined in the specified module.608*/609@Override610protected Class<?> findClass(String mn, String cn) {611if (mn != null) {612// find the candidate module for this class613LoadedModule loadedModule = findLoadedModule(mn, cn);614if (loadedModule == null) {615return null;616}617618// attempt to load class in module defined to this loader619assert loadedModule.loader() == this;620return findClassInModuleOrNull(loadedModule, cn);621}622623// search class path624if (hasClassPath()) {625return findClassOnClassPathOrNull(cn);626}627628return null;629}630631/**632* Loads the class with the specified binary name.633*/634@Override635protected Class<?> loadClass(String cn, boolean resolve)636throws ClassNotFoundException637{638Class<?> c = loadClassOrNull(cn, resolve);639if (c == null)640throw new ClassNotFoundException(cn);641return c;642}643644/**645* A variation of {@code loadClass} to load a class with the specified646* binary name. This method returns {@code null} when the class is not647* found.648*/649protected Class<?> loadClassOrNull(String cn, boolean resolve) {650synchronized (getClassLoadingLock(cn)) {651// check if already loaded652Class<?> c = findLoadedClass(cn);653654if (c == null) {655656// find the candidate module for this class657LoadedModule loadedModule = findLoadedModule(cn);658if (loadedModule != null) {659660// package is in a module661BuiltinClassLoader loader = loadedModule.loader();662if (loader == this) {663if (VM.isModuleSystemInited()) {664c = findClassInModuleOrNull(loadedModule, cn);665}666} else {667// delegate to the other loader668c = loader.loadClassOrNull(cn);669}670671} else {672673// check parent674if (parent != null) {675c = parent.loadClassOrNull(cn);676}677678// check class path679if (c == null && hasClassPath() && VM.isModuleSystemInited()) {680c = findClassOnClassPathOrNull(cn);681}682}683684}685686if (resolve && c != null)687resolveClass(c);688689return c;690}691}692693/**694* A variation of {@code loadClass} to load a class with the specified695* binary name. This method returns {@code null} when the class is not696* found.697*/698protected final Class<?> loadClassOrNull(String cn) {699return loadClassOrNull(cn, false);700}701702/**703* Finds the candidate loaded module for the given class name.704* Returns {@code null} if none of the modules defined to this705* class loader contain the API package for the class.706*/707private LoadedModule findLoadedModule(String cn) {708int pos = cn.lastIndexOf('.');709if (pos < 0)710return null; // unnamed package711712String pn = cn.substring(0, pos);713return packageToModule.get(pn);714}715716/**717* Finds the candidate loaded module for the given class name718* in the named module. Returns {@code null} if the named module719* is not defined to this class loader or does not contain720* the API package for the class.721*/722private LoadedModule findLoadedModule(String mn, String cn) {723LoadedModule loadedModule = findLoadedModule(cn);724if (loadedModule != null && mn.equals(loadedModule.name())) {725return loadedModule;726} else {727return null;728}729}730731/**732* Finds the class with the specified binary name if in a module733* defined to this ClassLoader.734*735* @return the resulting Class or {@code null} if not found736*/737@SuppressWarnings("removal")738private Class<?> findClassInModuleOrNull(LoadedModule loadedModule, String cn) {739if (System.getSecurityManager() == null) {740return defineClass(cn, loadedModule);741} else {742PrivilegedAction<Class<?>> pa = () -> defineClass(cn, loadedModule);743return AccessController.doPrivileged(pa);744}745}746747/**748* Finds the class with the specified binary name on the class path.749*750* @return the resulting Class or {@code null} if not found751*/752@SuppressWarnings("removal")753private Class<?> findClassOnClassPathOrNull(String cn) {754String path = cn.replace('.', '/').concat(".class");755if (System.getSecurityManager() == null) {756Resource res = ucp.getResource(path, false);757if (res != null) {758try {759return defineClass(cn, res);760} catch (IOException ioe) {761// TBD on how I/O errors should be propagated762}763}764return null;765} else {766// avoid use of lambda here767PrivilegedAction<Class<?>> pa = new PrivilegedAction<>() {768public Class<?> run() {769Resource res = ucp.getResource(path, false);770if (res != null) {771try {772return defineClass(cn, res);773} catch (IOException ioe) {774// TBD on how I/O errors should be propagated775}776}777return null;778}779};780return AccessController.doPrivileged(pa);781}782}783784/**785* Defines the given binary class name to the VM, loading the class786* bytes from the given module.787*788* @return the resulting Class or {@code null} if an I/O error occurs789*/790private Class<?> defineClass(String cn, LoadedModule loadedModule) {791ModuleReference mref = loadedModule.mref();792ModuleReader reader = moduleReaderFor(mref);793794try {795ByteBuffer bb = null;796URL csURL = null;797798// locate class file, special handling for patched modules to799// avoid locating the resource twice800String rn = cn.replace('.', '/').concat(".class");801if (reader instanceof PatchedModuleReader) {802Resource r = ((PatchedModuleReader)reader).findResource(rn);803if (r != null) {804bb = r.getByteBuffer();805csURL = r.getCodeSourceURL();806}807} else {808bb = reader.read(rn).orElse(null);809csURL = loadedModule.codeSourceURL();810}811812if (bb == null) {813// class not found814return null;815}816817CodeSource cs = new CodeSource(csURL, (CodeSigner[]) null);818try {819// define class to VM820return defineClass(cn, bb, cs);821822} finally {823reader.release(bb);824}825826} catch (IOException ioe) {827// TBD on how I/O errors should be propagated828return null;829}830}831832/**833* Defines the given binary class name to the VM, loading the class834* bytes via the given Resource object.835*836* @return the resulting Class837* @throws IOException if reading the resource fails838* @throws SecurityException if there is a sealing violation (JAR spec)839*/840private Class<?> defineClass(String cn, Resource res) throws IOException {841URL url = res.getCodeSourceURL();842843// if class is in a named package then ensure that the package is defined844int pos = cn.lastIndexOf('.');845if (pos != -1) {846String pn = cn.substring(0, pos);847Manifest man = res.getManifest();848defineOrCheckPackage(pn, man, url);849}850851// defines the class to the runtime852ByteBuffer bb = res.getByteBuffer();853if (bb != null) {854CodeSigner[] signers = res.getCodeSigners();855CodeSource cs = new CodeSource(url, signers);856return defineClass(cn, bb, cs);857} else {858byte[] b = res.getBytes();859CodeSigner[] signers = res.getCodeSigners();860CodeSource cs = new CodeSource(url, signers);861return defineClass(cn, b, 0, b.length, cs);862}863}864865866// -- packages867868/**869* Defines a package in this ClassLoader. If the package is already defined870* then its sealing needs to be checked if sealed by the legacy sealing871* mechanism.872*873* @throws SecurityException if there is a sealing violation (JAR spec)874*/875protected Package defineOrCheckPackage(String pn, Manifest man, URL url) {876Package pkg = getAndVerifyPackage(pn, man, url);877if (pkg == null) {878try {879if (man != null) {880pkg = definePackage(pn, man, url);881} else {882pkg = definePackage(pn, null, null, null, null, null, null, null);883}884} catch (IllegalArgumentException iae) {885// defined by another thread so need to re-verify886pkg = getAndVerifyPackage(pn, man, url);887if (pkg == null)888throw new InternalError("Cannot find package: " + pn);889}890}891return pkg;892}893894/**895* Gets the Package with the specified package name. If defined896* then verifies it against the manifest and code source.897*898* @throws SecurityException if there is a sealing violation (JAR spec)899*/900private Package getAndVerifyPackage(String pn, Manifest man, URL url) {901Package pkg = getDefinedPackage(pn);902if (pkg != null) {903if (pkg.isSealed()) {904if (!pkg.isSealed(url)) {905throw new SecurityException(906"sealing violation: package " + pn + " is sealed");907}908} else {909// can't seal package if already defined without sealing910if ((man != null) && isSealed(pn, man)) {911throw new SecurityException(912"sealing violation: can't seal package " + pn +913": already defined");914}915}916}917return pkg;918}919920/**921* Defines a new package in this ClassLoader. The attributes in the specified922* Manifest are used to get the package version and sealing information.923*924* @throws IllegalArgumentException if the package name duplicates an925* existing package either in this class loader or one of its ancestors926* @throws SecurityException if the package name is untrusted in the manifest927*/928private Package definePackage(String pn, Manifest man, URL url) {929String specTitle = null;930String specVersion = null;931String specVendor = null;932String implTitle = null;933String implVersion = null;934String implVendor = null;935String sealed = null;936URL sealBase = null;937938if (man != null) {939Attributes attr = SharedSecrets.javaUtilJarAccess()940.getTrustedAttributes(man, pn.replace('.', '/').concat("/"));941if (attr != null) {942specTitle = attr.getValue(Attributes.Name.SPECIFICATION_TITLE);943specVersion = attr.getValue(Attributes.Name.SPECIFICATION_VERSION);944specVendor = attr.getValue(Attributes.Name.SPECIFICATION_VENDOR);945implTitle = attr.getValue(Attributes.Name.IMPLEMENTATION_TITLE);946implVersion = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION);947implVendor = attr.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);948sealed = attr.getValue(Attributes.Name.SEALED);949}950951attr = man.getMainAttributes();952if (attr != null) {953if (specTitle == null)954specTitle = attr.getValue(Attributes.Name.SPECIFICATION_TITLE);955if (specVersion == null)956specVersion = attr.getValue(Attributes.Name.SPECIFICATION_VERSION);957if (specVendor == null)958specVendor = attr.getValue(Attributes.Name.SPECIFICATION_VENDOR);959if (implTitle == null)960implTitle = attr.getValue(Attributes.Name.IMPLEMENTATION_TITLE);961if (implVersion == null)962implVersion = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION);963if (implVendor == null)964implVendor = attr.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);965if (sealed == null)966sealed = attr.getValue(Attributes.Name.SEALED);967}968969// package is sealed970if ("true".equalsIgnoreCase(sealed))971sealBase = url;972}973return definePackage(pn,974specTitle,975specVersion,976specVendor,977implTitle,978implVersion,979implVendor,980sealBase);981}982983/**984* Returns {@code true} if the specified package name is sealed according to985* the given manifest.986*987* @throws SecurityException if the package name is untrusted in the manifest988*/989private boolean isSealed(String pn, Manifest man) {990Attributes attr = SharedSecrets.javaUtilJarAccess()991.getTrustedAttributes(man, pn.replace('.', '/').concat("/"));992String sealed = null;993if (attr != null)994sealed = attr.getValue(Attributes.Name.SEALED);995if (sealed == null && (attr = man.getMainAttributes()) != null)996sealed = attr.getValue(Attributes.Name.SEALED);997return "true".equalsIgnoreCase(sealed);998}9991000// -- permissions10011002/**1003* Returns the permissions for the given CodeSource.1004*/1005@Override1006protected PermissionCollection getPermissions(CodeSource cs) {1007return new LazyCodeSourcePermissionCollection(super.getPermissions(cs), cs);1008}10091010// -- miscellaneous supporting methods10111012/**1013* Returns the ModuleReader for the given module, creating it if needed.1014*/1015private ModuleReader moduleReaderFor(ModuleReference mref) {1016ModuleReader reader = moduleToReader.get(mref);1017if (reader == null) {1018// avoid method reference during startup1019Function<ModuleReference, ModuleReader> create = new Function<>() {1020public ModuleReader apply(ModuleReference moduleReference) {1021try {1022return mref.open();1023} catch (IOException e) {1024// Return a null module reader to avoid a future class1025// load attempting to open the module again.1026return new NullModuleReader();1027}1028}1029};1030reader = moduleToReader.computeIfAbsent(mref, create);1031}1032return reader;1033}10341035/**1036* A ModuleReader that doesn't read any resources.1037*/1038private static class NullModuleReader implements ModuleReader {1039@Override1040public Optional<URI> find(String name) {1041return Optional.empty();1042}1043@Override1044public Stream<String> list() {1045return Stream.empty();1046}1047@Override1048public void close() {1049throw new InternalError("Should not get here");1050}1051};10521053/**1054* Returns true if the given module opens the given package1055* unconditionally.1056*1057* @implNote This method currently iterates over each of the open1058* packages. This will be replaced once the ModuleDescriptor.Opens1059* API is updated.1060*/1061private boolean isOpen(ModuleReference mref, String pn) {1062ModuleDescriptor descriptor = mref.descriptor();1063if (descriptor.isOpen() || descriptor.isAutomatic())1064return true;1065for (ModuleDescriptor.Opens opens : descriptor.opens()) {1066String source = opens.source();1067if (!opens.isQualified() && source.equals(pn)) {1068return true;1069}1070}1071return false;1072}10731074/**1075* Checks access to the given URL. We use URLClassPath for consistent1076* checking with java.net.URLClassLoader.1077*/1078private static URL checkURL(URL url) {1079return URLClassPath.checkURL(url);1080}10811082// Called from VM only, during -Xshare:dump1083private void resetArchivedStates() {1084ucp = null;1085}1086}108710881089