29 import java.io.InputStream;
30 import java.lang.module.ModuleDescriptor;
31 import java.lang.module.ModuleReference;
32 import java.lang.module.ModuleReader;
33 import java.lang.ref.SoftReference;
34 import java.net.MalformedURLException;
35 import java.net.URI;
36 import java.net.URL;
37 import java.nio.ByteBuffer;
38 import java.security.CodeSigner;
39 import java.security.CodeSource;
40 import java.security.SecureClassLoader;
41 import java.util.ArrayList;
42 import java.util.Collections;
43 import java.util.Enumeration;
44 import java.util.Iterator;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.NoSuchElementException;
48 import java.util.Optional;
49 import java.util.concurrent.ConcurrentHashMap;
50 import java.util.function.Function;
51 import java.util.jar.Attributes;
52 import java.util.jar.Manifest;
53 import java.util.stream.Stream;
54
55 import jdk.internal.access.SharedSecrets;
56 import jdk.internal.misc.VM;
57 import jdk.internal.module.ModulePatcher.PatchedModuleReader;
58 import jdk.internal.module.Resources;
59 import jdk.internal.vm.annotation.Stable;
60
61
62 /**
63 * The platform or application class loader. Resources loaded from modules
64 * defined to the boot class loader are also loaded via an instance of this
65 * ClassLoader type.
66 *
67 * <p> This ClassLoader supports loading of classes and resources from modules.
68 * Modules are defined to the ClassLoader by invoking the {@link #loadModule}
69 * method. Defining a module to this ClassLoader has the effect of making the
70 * types in the module visible. </p>
71 *
72 * <p> This ClassLoader also supports loading of classes and resources from a
73 * class path of URLs that are specified to the ClassLoader at construction
74 * time. The class path may expand at runtime (the Class-Path attribute in JAR
75 * files or via instrumentation agents). </p>
83 * found in the parent then it searches the class path. The main difference
84 * between this and the usual delegation model is that it allows the platform
85 * class loader to delegate to the application class loader, important with
86 * upgraded modules defined to the platform class loader.
87 */
88
89 public class BuiltinClassLoader
90 extends SecureClassLoader
91 {
92 static {
93 if (!ClassLoader.registerAsParallelCapable())
94 throw new InternalError("Unable to register as parallel capable");
95 }
96
97 // parent ClassLoader
98 private final BuiltinClassLoader parent;
99
100 // the URL class path, or null if there is no class path
101 private @Stable URLClassPath ucp;
102
103 /**
104 * A module defined/loaded by a built-in class loader.
105 *
106 * A LoadedModule encapsulates a ModuleReference along with its CodeSource
107 * URL to avoid needing to create this URL when defining classes.
108 */
109 private static class LoadedModule {
110 private final BuiltinClassLoader loader;
111 private final ModuleReference mref;
112 private final URI uri; // may be null
113 private @Stable URL codeSourceURL; // may be null
114
115 LoadedModule(BuiltinClassLoader loader, ModuleReference mref) {
116 URL url = null;
117 this.uri = mref.location().orElse(null);
118
119 // for non-jrt schemes we need to resolve the codeSourceURL
120 // eagerly during bootstrap since the handler might be
121 // overridden
122 if (uri != null && !"jrt".equals(uri.getScheme())) {
175
176 // maps a module reference to a module reader
177 private final Map<ModuleReference, ModuleReader> moduleToReader;
178
179 // cache of resource name -> list of URLs.
180 // used only for resources that are not in module packages
181 private volatile SoftReference<Map<String, List<URL>>> resourceCache;
182
183 /**
184 * Create a new instance.
185 */
186 BuiltinClassLoader(String name, BuiltinClassLoader parent, URLClassPath ucp) {
187 // ensure getParent() returns null when the parent is the boot loader
188 super(name, parent == null || parent == ClassLoaders.bootLoader() ? null : parent);
189
190 this.parent = parent;
191 this.ucp = ucp;
192
193 this.nameToModule = new ConcurrentHashMap<>(32);
194 this.moduleToReader = new ConcurrentHashMap<>();
195 }
196
197 /**
198 * Appends to the given file path to the class path.
199 */
200 void appendClassPath(String path) {
201 // assert ucp != null;
202 ucp.addFile(path);
203 }
204
205 /**
206 * Sets the class path, called to reset the class path during -Xshare:dump
207 */
208 void setClassPath(URLClassPath ucp) {
209 this.ucp = ucp;
210 }
211
212 /**
213 * Returns {@code true} if there is a class path associated with this
214 * class loader.
559 // attempt to load class in module defined to this loader
560 assert loadedModule.loader() == this;
561 return findClassInModuleOrNull(loadedModule, cn);
562 }
563
564 // search class path
565 if (hasClassPath()) {
566 return findClassOnClassPathOrNull(cn);
567 }
568
569 return null;
570 }
571
572 /**
573 * Loads the class with the specified binary name.
574 */
575 @Override
576 protected Class<?> loadClass(String cn, boolean resolve)
577 throws ClassNotFoundException
578 {
579 Class<?> c = loadClassOrNull(cn, resolve);
580 if (c == null)
581 throw new ClassNotFoundException(cn);
582 return c;
583 }
584
585 /**
586 * A variation of {@code loadClass} to load a class with the specified
587 * binary name. This method returns {@code null} when the class is not
588 * found.
589 */
590 protected Class<?> loadClassOrNull(String cn, boolean resolve) {
591 synchronized (getClassLoadingLock(cn)) {
592 // check if already loaded
593 Class<?> c = findLoadedClass(cn);
594
595 if (c == null) {
596
597 // find the candidate module for this class
598 LoadedModule loadedModule = findLoadedModule(cn);
599 if (loadedModule != null) {
600
601 // package is in a module
968 ModuleDescriptor descriptor = mref.descriptor();
969 if (descriptor.isOpen() || descriptor.isAutomatic())
970 return true;
971 for (ModuleDescriptor.Opens opens : descriptor.opens()) {
972 String source = opens.source();
973 if (!opens.isQualified() && source.equals(pn)) {
974 return true;
975 }
976 }
977 return false;
978 }
979
980 // Called from VM only, during -Xshare:dump
981 private void resetArchivedStates() {
982 ucp = null;
983 resourceCache = null;
984 if (!moduleToReader.isEmpty()) {
985 moduleToReader.clear();
986 }
987 }
988 }
|
29 import java.io.InputStream;
30 import java.lang.module.ModuleDescriptor;
31 import java.lang.module.ModuleReference;
32 import java.lang.module.ModuleReader;
33 import java.lang.ref.SoftReference;
34 import java.net.MalformedURLException;
35 import java.net.URI;
36 import java.net.URL;
37 import java.nio.ByteBuffer;
38 import java.security.CodeSigner;
39 import java.security.CodeSource;
40 import java.security.SecureClassLoader;
41 import java.util.ArrayList;
42 import java.util.Collections;
43 import java.util.Enumeration;
44 import java.util.Iterator;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.NoSuchElementException;
48 import java.util.Optional;
49 import java.util.Set;
50 import java.util.concurrent.ConcurrentHashMap;
51 import java.util.function.Function;
52 import java.util.jar.Attributes;
53 import java.util.jar.Manifest;
54 import java.util.stream.Stream;
55
56 import jdk.internal.access.SharedSecrets;
57 import jdk.internal.misc.CDS;
58 import jdk.internal.misc.VM;
59 import jdk.internal.module.ModulePatcher.PatchedModuleReader;
60 import jdk.internal.module.Resources;
61 import jdk.internal.vm.annotation.Stable;
62
63
64 /**
65 * The platform or application class loader. Resources loaded from modules
66 * defined to the boot class loader are also loaded via an instance of this
67 * ClassLoader type.
68 *
69 * <p> This ClassLoader supports loading of classes and resources from modules.
70 * Modules are defined to the ClassLoader by invoking the {@link #loadModule}
71 * method. Defining a module to this ClassLoader has the effect of making the
72 * types in the module visible. </p>
73 *
74 * <p> This ClassLoader also supports loading of classes and resources from a
75 * class path of URLs that are specified to the ClassLoader at construction
76 * time. The class path may expand at runtime (the Class-Path attribute in JAR
77 * files or via instrumentation agents). </p>
85 * found in the parent then it searches the class path. The main difference
86 * between this and the usual delegation model is that it allows the platform
87 * class loader to delegate to the application class loader, important with
88 * upgraded modules defined to the platform class loader.
89 */
90
91 public class BuiltinClassLoader
92 extends SecureClassLoader
93 {
94 static {
95 if (!ClassLoader.registerAsParallelCapable())
96 throw new InternalError("Unable to register as parallel capable");
97 }
98
99 // parent ClassLoader
100 private final BuiltinClassLoader parent;
101
102 // the URL class path, or null if there is no class path
103 private @Stable URLClassPath ucp;
104
105 private Set<String> negativeLookupCache;
106 private Map<String, Class<? extends Object>> positiveLookupCache;
107
108 public boolean useNegativeCache = false;
109 public boolean usePositiveCache = false;
110
111 /**
112 * A module defined/loaded by a built-in class loader.
113 *
114 * A LoadedModule encapsulates a ModuleReference along with its CodeSource
115 * URL to avoid needing to create this URL when defining classes.
116 */
117 private static class LoadedModule {
118 private final BuiltinClassLoader loader;
119 private final ModuleReference mref;
120 private final URI uri; // may be null
121 private @Stable URL codeSourceURL; // may be null
122
123 LoadedModule(BuiltinClassLoader loader, ModuleReference mref) {
124 URL url = null;
125 this.uri = mref.location().orElse(null);
126
127 // for non-jrt schemes we need to resolve the codeSourceURL
128 // eagerly during bootstrap since the handler might be
129 // overridden
130 if (uri != null && !"jrt".equals(uri.getScheme())) {
183
184 // maps a module reference to a module reader
185 private final Map<ModuleReference, ModuleReader> moduleToReader;
186
187 // cache of resource name -> list of URLs.
188 // used only for resources that are not in module packages
189 private volatile SoftReference<Map<String, List<URL>>> resourceCache;
190
191 /**
192 * Create a new instance.
193 */
194 BuiltinClassLoader(String name, BuiltinClassLoader parent, URLClassPath ucp) {
195 // ensure getParent() returns null when the parent is the boot loader
196 super(name, parent == null || parent == ClassLoaders.bootLoader() ? null : parent);
197
198 this.parent = parent;
199 this.ucp = ucp;
200
201 this.nameToModule = new ConcurrentHashMap<>(32);
202 this.moduleToReader = new ConcurrentHashMap<>();
203 this.negativeLookupCache = ConcurrentHashMap.newKeySet();
204 this.positiveLookupCache = new ConcurrentHashMap<>();
205 }
206
207 /**
208 * Appends to the given file path to the class path.
209 */
210 void appendClassPath(String path) {
211 // assert ucp != null;
212 ucp.addFile(path);
213 }
214
215 /**
216 * Sets the class path, called to reset the class path during -Xshare:dump
217 */
218 void setClassPath(URLClassPath ucp) {
219 this.ucp = ucp;
220 }
221
222 /**
223 * Returns {@code true} if there is a class path associated with this
224 * class loader.
569 // attempt to load class in module defined to this loader
570 assert loadedModule.loader() == this;
571 return findClassInModuleOrNull(loadedModule, cn);
572 }
573
574 // search class path
575 if (hasClassPath()) {
576 return findClassOnClassPathOrNull(cn);
577 }
578
579 return null;
580 }
581
582 /**
583 * Loads the class with the specified binary name.
584 */
585 @Override
586 protected Class<?> loadClass(String cn, boolean resolve)
587 throws ClassNotFoundException
588 {
589 if (useNegativeCache && checkNegativeLookupCache(cn)) {
590 throw new ClassNotFoundException(cn);
591 }
592 Class<?> c = loadClassOrNull(cn, resolve);
593 if (c == null) {
594 addToNegativeLookupCache(cn);
595 throw new ClassNotFoundException(cn);
596 }
597
598 return c;
599 }
600
601 /**
602 * A variation of {@code loadClass} to load a class with the specified
603 * binary name. This method returns {@code null} when the class is not
604 * found.
605 */
606 protected Class<?> loadClassOrNull(String cn, boolean resolve) {
607 synchronized (getClassLoadingLock(cn)) {
608 // check if already loaded
609 Class<?> c = findLoadedClass(cn);
610
611 if (c == null) {
612
613 // find the candidate module for this class
614 LoadedModule loadedModule = findLoadedModule(cn);
615 if (loadedModule != null) {
616
617 // package is in a module
984 ModuleDescriptor descriptor = mref.descriptor();
985 if (descriptor.isOpen() || descriptor.isAutomatic())
986 return true;
987 for (ModuleDescriptor.Opens opens : descriptor.opens()) {
988 String source = opens.source();
989 if (!opens.isQualified() && source.equals(pn)) {
990 return true;
991 }
992 }
993 return false;
994 }
995
996 // Called from VM only, during -Xshare:dump
997 private void resetArchivedStates() {
998 ucp = null;
999 resourceCache = null;
1000 if (!moduleToReader.isEmpty()) {
1001 moduleToReader.clear();
1002 }
1003 }
1004
1005 public boolean checkNegativeLookupCache(String className) {
1006 return negativeLookupCache.contains(className);
1007 }
1008
1009 public void addToNegativeLookupCache(String className) {
1010 negativeLookupCache.add(className);
1011 }
1012
1013 public String negativeLookupCacheContents() {
1014 String[] contents = negativeLookupCache.toArray(new String[]{});
1015 StringBuilder builder = new StringBuilder();
1016 if (contents.length != 0) {
1017 for (String name: contents) {
1018 if (builder.length() != 0) {
1019 builder.append(" ");
1020 }
1021 builder.append(name);
1022 }
1023 return builder.toString();
1024 } else {
1025 return null;
1026 }
1027 }
1028
1029 public void generateNegativeLookupCache(String contents) {
1030 String[] tokens = contents.split(" ");
1031 if (tokens.length > 0) {
1032 for (String token : tokens) {
1033 negativeLookupCache.add(token);
1034 }
1035 useNegativeCache = true;
1036 }
1037 }
1038
1039 public Class<?> checkPositiveLookupCache(String className) {
1040 return positiveLookupCache.get(className);
1041 }
1042
1043 public void generatePositiveLookupCache(Class<?>[] cls) {
1044 if (cls.length > 0) {
1045 for (Class<?> c : cls) {
1046 positiveLookupCache.put(c.getName(), c);
1047 }
1048 usePositiveCache = true;
1049 }
1050 }
1051 }
|