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.
558 // attempt to load class in module defined to this loader
559 assert loadedModule.loader() == this;
560 return findClassInModuleOrNull(loadedModule, cn);
561 }
562
563 // search class path
564 if (hasClassPath()) {
565 return findClassOnClassPathOrNull(cn);
566 }
567
568 return null;
569 }
570
571 /**
572 * Loads the class with the specified binary name.
573 */
574 @Override
575 protected Class<?> loadClass(String cn, boolean resolve)
576 throws ClassNotFoundException
577 {
578 Class<?> c = loadClassOrNull(cn, resolve);
579 if (c == null)
580 throw new ClassNotFoundException(cn);
581 return c;
582 }
583
584 /**
585 * A variation of {@code loadClass} to load a class with the specified
586 * binary name. This method returns {@code null} when the class is not
587 * found.
588 */
589 protected Class<?> loadClassOrNull(String cn, boolean resolve) {
590 synchronized (getClassLoadingLock(cn)) {
591 // check if already loaded
592 Class<?> c = findLoadedClass(cn);
593
594 if (c == null) {
595
596 // find the candidate module for this class
597 LoadedModule loadedModule = findLoadedModule(cn);
598 if (loadedModule != null) {
599
600 // package is in a module
967 ModuleDescriptor descriptor = mref.descriptor();
968 if (descriptor.isOpen() || descriptor.isAutomatic())
969 return true;
970 for (ModuleDescriptor.Opens opens : descriptor.opens()) {
971 String source = opens.source();
972 if (!opens.isQualified() && source.equals(pn)) {
973 return true;
974 }
975 }
976 return false;
977 }
978
979 // Called from VM only, during -Xshare:dump
980 private void resetArchivedStates() {
981 ucp = null;
982 resourceCache = null;
983 if (!moduleToReader.isEmpty()) {
984 moduleToReader.clear();
985 }
986 }
987 }
|
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.
568 // attempt to load class in module defined to this loader
569 assert loadedModule.loader() == this;
570 return findClassInModuleOrNull(loadedModule, cn);
571 }
572
573 // search class path
574 if (hasClassPath()) {
575 return findClassOnClassPathOrNull(cn);
576 }
577
578 return null;
579 }
580
581 /**
582 * Loads the class with the specified binary name.
583 */
584 @Override
585 protected Class<?> loadClass(String cn, boolean resolve)
586 throws ClassNotFoundException
587 {
588 if (useNegativeCache && checkNegativeLookupCache(cn)) {
589 throw new ClassNotFoundException(cn);
590 }
591 Class<?> c = loadClassOrNull(cn, resolve);
592 if (c == null) {
593 addToNegativeLookupCache(cn);
594 throw new ClassNotFoundException(cn);
595 }
596
597 return c;
598 }
599
600 /**
601 * A variation of {@code loadClass} to load a class with the specified
602 * binary name. This method returns {@code null} when the class is not
603 * found.
604 */
605 protected Class<?> loadClassOrNull(String cn, boolean resolve) {
606 synchronized (getClassLoadingLock(cn)) {
607 // check if already loaded
608 Class<?> c = findLoadedClass(cn);
609
610 if (c == null) {
611
612 // find the candidate module for this class
613 LoadedModule loadedModule = findLoadedModule(cn);
614 if (loadedModule != null) {
615
616 // package is in a module
983 ModuleDescriptor descriptor = mref.descriptor();
984 if (descriptor.isOpen() || descriptor.isAutomatic())
985 return true;
986 for (ModuleDescriptor.Opens opens : descriptor.opens()) {
987 String source = opens.source();
988 if (!opens.isQualified() && source.equals(pn)) {
989 return true;
990 }
991 }
992 return false;
993 }
994
995 // Called from VM only, during -Xshare:dump
996 private void resetArchivedStates() {
997 ucp = null;
998 resourceCache = null;
999 if (!moduleToReader.isEmpty()) {
1000 moduleToReader.clear();
1001 }
1002 }
1003
1004 public boolean checkNegativeLookupCache(String className) {
1005 return negativeLookupCache.contains(className);
1006 }
1007
1008 public void addToNegativeLookupCache(String className) {
1009 negativeLookupCache.add(className);
1010 }
1011
1012 public String negativeLookupCacheContents() {
1013 String[] contents = negativeLookupCache.toArray(new String[]{});
1014 StringBuilder builder = new StringBuilder();
1015 if (contents.length != 0) {
1016 for (String name: contents) {
1017 if (builder.length() != 0) {
1018 builder.append(" ");
1019 }
1020 builder.append(name);
1021 }
1022 return builder.toString();
1023 } else {
1024 return null;
1025 }
1026 }
1027
1028 public void generateNegativeLookupCache(String contents) {
1029 String[] tokens = contents.split(" ");
1030 if (tokens.length > 0) {
1031 for (String token : tokens) {
1032 negativeLookupCache.add(token);
1033 }
1034 useNegativeCache = true;
1035 }
1036 }
1037
1038 public Class<?> checkPositiveLookupCache(String className) {
1039 return positiveLookupCache.get(className);
1040 }
1041
1042 public void generatePositiveLookupCache(Class<?>[] cls) {
1043 if (cls.length > 0) {
1044 for (Class<?> c : cls) {
1045 positiveLookupCache.put(c.getName(), c);
1046 }
1047 usePositiveCache = true;
1048 }
1049 }
1050 }
|