34 import java.net.MalformedURLException;
35 import java.net.URI;
36 import java.net.URL;
37 import java.nio.ByteBuffer;
38 import java.security.AccessController;
39 import java.security.CodeSigner;
40 import java.security.CodeSource;
41 import java.security.PermissionCollection;
42 import java.security.PrivilegedAction;
43 import java.security.PrivilegedActionException;
44 import java.security.PrivilegedExceptionAction;
45 import java.security.SecureClassLoader;
46 import java.util.ArrayList;
47 import java.util.Collections;
48 import java.util.Enumeration;
49 import java.util.Iterator;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.NoSuchElementException;
53 import java.util.Optional;
54 import java.util.concurrent.ConcurrentHashMap;
55 import java.util.function.Function;
56 import java.util.jar.Attributes;
57 import java.util.jar.Manifest;
58 import java.util.stream.Stream;
59
60 import jdk.internal.access.SharedSecrets;
61 import jdk.internal.misc.VM;
62 import jdk.internal.module.ModulePatcher.PatchedModuleReader;
63 import jdk.internal.module.Resources;
64 import jdk.internal.vm.annotation.Stable;
65 import sun.security.util.LazyCodeSourcePermissionCollection;
66
67
68 /**
69 * The platform or application class loader. Resources loaded from modules
70 * defined to the boot class loader are also loaded via an instance of this
71 * ClassLoader type.
72 *
73 * <p> This ClassLoader supports loading of classes and resources from modules.
74 * Modules are defined to the ClassLoader by invoking the {@link #loadModule}
75 * method. Defining a module to this ClassLoader has the effect of making the
76 * types in the module visible. </p>
77 *
78 * <p> This ClassLoader also supports loading of classes and resources from a
79 * class path of URLs that are specified to the ClassLoader at construction
80 * time. The class path may expand at runtime (the Class-Path attribute in JAR
89 * found in the parent then it searches the class path. The main difference
90 * between this and the usual delegation model is that it allows the platform
91 * class loader to delegate to the application class loader, important with
92 * upgraded modules defined to the platform class loader.
93 */
94
95 public class BuiltinClassLoader
96 extends SecureClassLoader
97 {
98 static {
99 if (!ClassLoader.registerAsParallelCapable())
100 throw new InternalError("Unable to register as parallel capable");
101 }
102
103 // parent ClassLoader
104 private final BuiltinClassLoader parent;
105
106 // the URL class path, or null if there is no class path
107 private @Stable URLClassPath ucp;
108
109 /**
110 * A module defined/loaded by a built-in class loader.
111 *
112 * A LoadedModule encapsulates a ModuleReference along with its CodeSource
113 * URL to avoid needing to create this URL when defining classes.
114 */
115 private static class LoadedModule {
116 private final BuiltinClassLoader loader;
117 private final ModuleReference mref;
118 private final URI uri; // may be null
119 private @Stable URL codeSourceURL; // may be null
120
121 LoadedModule(BuiltinClassLoader loader, ModuleReference mref) {
122 URL url = null;
123 this.uri = mref.location().orElse(null);
124
125 // for non-jrt schemes we need to resolve the codeSourceURL
126 // eagerly during bootstrap since the handler might be
127 // overridden
128 if (uri != null && !"jrt".equals(uri.getScheme())) {
181
182 // maps a module reference to a module reader
183 private final Map<ModuleReference, ModuleReader> moduleToReader;
184
185 // cache of resource name -> list of URLs.
186 // used only for resources that are not in module packages
187 private volatile SoftReference<Map<String, List<URL>>> resourceCache;
188
189 /**
190 * Create a new instance.
191 */
192 BuiltinClassLoader(String name, BuiltinClassLoader parent, URLClassPath ucp) {
193 // ensure getParent() returns null when the parent is the boot loader
194 super(name, parent == null || parent == ClassLoaders.bootLoader() ? null : parent);
195
196 this.parent = parent;
197 this.ucp = ucp;
198
199 this.nameToModule = new ConcurrentHashMap<>(32);
200 this.moduleToReader = new ConcurrentHashMap<>();
201 }
202
203 /**
204 * Appends to the given file path to the class path.
205 */
206 void appendClassPath(String path) {
207 // assert ucp != null;
208 ucp.addFile(path);
209 }
210
211 /**
212 * Sets the class path, called to reset the class path during -Xshare:dump
213 */
214 void setClassPath(URLClassPath ucp) {
215 this.ucp = ucp;
216 }
217
218 /**
219 * Returns {@code true} if there is a class path associated with this
220 * class loader.
619 // attempt to load class in module defined to this loader
620 assert loadedModule.loader() == this;
621 return findClassInModuleOrNull(loadedModule, cn);
622 }
623
624 // search class path
625 if (hasClassPath()) {
626 return findClassOnClassPathOrNull(cn);
627 }
628
629 return null;
630 }
631
632 /**
633 * Loads the class with the specified binary name.
634 */
635 @Override
636 protected Class<?> loadClass(String cn, boolean resolve)
637 throws ClassNotFoundException
638 {
639 Class<?> c = loadClassOrNull(cn, resolve);
640 if (c == null)
641 throw new ClassNotFoundException(cn);
642 return c;
643 }
644
645 /**
646 * A variation of {@code loadClass} to load a class with the specified
647 * binary name. This method returns {@code null} when the class is not
648 * found.
649 */
650 protected Class<?> loadClassOrNull(String cn, boolean resolve) {
651 synchronized (getClassLoadingLock(cn)) {
652 // check if already loaded
653 Class<?> c = findLoadedClass(cn);
654
655 if (c == null) {
656
657 // find the candidate module for this class
658 LoadedModule loadedModule = findLoadedModule(cn);
659 if (loadedModule != null) {
660
661 // package is in a module
1071 }
1072 return false;
1073 }
1074
1075 /**
1076 * Checks access to the given URL. We use URLClassPath for consistent
1077 * checking with java.net.URLClassLoader.
1078 */
1079 private static URL checkURL(URL url) {
1080 return URLClassPath.checkURL(url);
1081 }
1082
1083 // Called from VM only, during -Xshare:dump
1084 private void resetArchivedStates() {
1085 ucp = null;
1086 resourceCache = null;
1087 if (!moduleToReader.isEmpty()) {
1088 moduleToReader.clear();
1089 }
1090 }
1091 }
|
34 import java.net.MalformedURLException;
35 import java.net.URI;
36 import java.net.URL;
37 import java.nio.ByteBuffer;
38 import java.security.AccessController;
39 import java.security.CodeSigner;
40 import java.security.CodeSource;
41 import java.security.PermissionCollection;
42 import java.security.PrivilegedAction;
43 import java.security.PrivilegedActionException;
44 import java.security.PrivilegedExceptionAction;
45 import java.security.SecureClassLoader;
46 import java.util.ArrayList;
47 import java.util.Collections;
48 import java.util.Enumeration;
49 import java.util.Iterator;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.NoSuchElementException;
53 import java.util.Optional;
54 import java.util.Set;
55 import java.util.concurrent.ConcurrentHashMap;
56 import java.util.function.Function;
57 import java.util.jar.Attributes;
58 import java.util.jar.Manifest;
59 import java.util.stream.Stream;
60
61 import jdk.internal.access.SharedSecrets;
62 import jdk.internal.misc.CDS;
63 import jdk.internal.misc.VM;
64 import jdk.internal.module.ModulePatcher.PatchedModuleReader;
65 import jdk.internal.module.Resources;
66 import jdk.internal.vm.annotation.Stable;
67 import sun.security.util.LazyCodeSourcePermissionCollection;
68
69
70 /**
71 * The platform or application class loader. Resources loaded from modules
72 * defined to the boot class loader are also loaded via an instance of this
73 * ClassLoader type.
74 *
75 * <p> This ClassLoader supports loading of classes and resources from modules.
76 * Modules are defined to the ClassLoader by invoking the {@link #loadModule}
77 * method. Defining a module to this ClassLoader has the effect of making the
78 * types in the module visible. </p>
79 *
80 * <p> This ClassLoader also supports loading of classes and resources from a
81 * class path of URLs that are specified to the ClassLoader at construction
82 * time. The class path may expand at runtime (the Class-Path attribute in JAR
91 * found in the parent then it searches the class path. The main difference
92 * between this and the usual delegation model is that it allows the platform
93 * class loader to delegate to the application class loader, important with
94 * upgraded modules defined to the platform class loader.
95 */
96
97 public class BuiltinClassLoader
98 extends SecureClassLoader
99 {
100 static {
101 if (!ClassLoader.registerAsParallelCapable())
102 throw new InternalError("Unable to register as parallel capable");
103 }
104
105 // parent ClassLoader
106 private final BuiltinClassLoader parent;
107
108 // the URL class path, or null if there is no class path
109 private @Stable URLClassPath ucp;
110
111 private Set<String> negativeLookupCache;
112 private Map<String, Class<? extends Object>> positiveLookupCache;
113
114 public boolean useNegativeCache = false;
115 public boolean usePositiveCache = false;
116
117 /**
118 * A module defined/loaded by a built-in class loader.
119 *
120 * A LoadedModule encapsulates a ModuleReference along with its CodeSource
121 * URL to avoid needing to create this URL when defining classes.
122 */
123 private static class LoadedModule {
124 private final BuiltinClassLoader loader;
125 private final ModuleReference mref;
126 private final URI uri; // may be null
127 private @Stable URL codeSourceURL; // may be null
128
129 LoadedModule(BuiltinClassLoader loader, ModuleReference mref) {
130 URL url = null;
131 this.uri = mref.location().orElse(null);
132
133 // for non-jrt schemes we need to resolve the codeSourceURL
134 // eagerly during bootstrap since the handler might be
135 // overridden
136 if (uri != null && !"jrt".equals(uri.getScheme())) {
189
190 // maps a module reference to a module reader
191 private final Map<ModuleReference, ModuleReader> moduleToReader;
192
193 // cache of resource name -> list of URLs.
194 // used only for resources that are not in module packages
195 private volatile SoftReference<Map<String, List<URL>>> resourceCache;
196
197 /**
198 * Create a new instance.
199 */
200 BuiltinClassLoader(String name, BuiltinClassLoader parent, URLClassPath ucp) {
201 // ensure getParent() returns null when the parent is the boot loader
202 super(name, parent == null || parent == ClassLoaders.bootLoader() ? null : parent);
203
204 this.parent = parent;
205 this.ucp = ucp;
206
207 this.nameToModule = new ConcurrentHashMap<>(32);
208 this.moduleToReader = new ConcurrentHashMap<>();
209 this.negativeLookupCache = ConcurrentHashMap.newKeySet();
210 this.positiveLookupCache = new ConcurrentHashMap<>();
211 }
212
213 /**
214 * Appends to the given file path to the class path.
215 */
216 void appendClassPath(String path) {
217 // assert ucp != null;
218 ucp.addFile(path);
219 }
220
221 /**
222 * Sets the class path, called to reset the class path during -Xshare:dump
223 */
224 void setClassPath(URLClassPath ucp) {
225 this.ucp = ucp;
226 }
227
228 /**
229 * Returns {@code true} if there is a class path associated with this
230 * class loader.
629 // attempt to load class in module defined to this loader
630 assert loadedModule.loader() == this;
631 return findClassInModuleOrNull(loadedModule, cn);
632 }
633
634 // search class path
635 if (hasClassPath()) {
636 return findClassOnClassPathOrNull(cn);
637 }
638
639 return null;
640 }
641
642 /**
643 * Loads the class with the specified binary name.
644 */
645 @Override
646 protected Class<?> loadClass(String cn, boolean resolve)
647 throws ClassNotFoundException
648 {
649 if (useNegativeCache && checkNegativeLookupCache(cn)) {
650 throw new ClassNotFoundException(cn);
651 }
652 Class<?> c = loadClassOrNull(cn, resolve);
653 if (c == null) {
654 addToNegativeLookupCache(cn);
655 throw new ClassNotFoundException(cn);
656 }
657
658 return c;
659 }
660
661 /**
662 * A variation of {@code loadClass} to load a class with the specified
663 * binary name. This method returns {@code null} when the class is not
664 * found.
665 */
666 protected Class<?> loadClassOrNull(String cn, boolean resolve) {
667 synchronized (getClassLoadingLock(cn)) {
668 // check if already loaded
669 Class<?> c = findLoadedClass(cn);
670
671 if (c == null) {
672
673 // find the candidate module for this class
674 LoadedModule loadedModule = findLoadedModule(cn);
675 if (loadedModule != null) {
676
677 // package is in a module
1087 }
1088 return false;
1089 }
1090
1091 /**
1092 * Checks access to the given URL. We use URLClassPath for consistent
1093 * checking with java.net.URLClassLoader.
1094 */
1095 private static URL checkURL(URL url) {
1096 return URLClassPath.checkURL(url);
1097 }
1098
1099 // Called from VM only, during -Xshare:dump
1100 private void resetArchivedStates() {
1101 ucp = null;
1102 resourceCache = null;
1103 if (!moduleToReader.isEmpty()) {
1104 moduleToReader.clear();
1105 }
1106 }
1107
1108 public boolean checkNegativeLookupCache(String className) {
1109 return negativeLookupCache.contains(className);
1110 }
1111
1112 public void addToNegativeLookupCache(String className) {
1113 negativeLookupCache.add(className);
1114 }
1115
1116 public String negativeLookupCacheContents() {
1117 String[] contents = negativeLookupCache.toArray(new String[]{});
1118 StringBuilder builder = new StringBuilder();
1119 if (contents.length != 0) {
1120 for (String name: contents) {
1121 if (builder.length() != 0) {
1122 builder.append(" ");
1123 }
1124 builder.append(name);
1125 }
1126 return builder.toString();
1127 } else {
1128 return null;
1129 }
1130 }
1131
1132 public void generateNegativeLookupCache(String contents) {
1133 String[] tokens = contents.split(" ");
1134 if (tokens.length > 0) {
1135 for (String token : tokens) {
1136 negativeLookupCache.add(token);
1137 }
1138 useNegativeCache = true;
1139 }
1140 }
1141
1142 public Class<?> checkPositiveLookupCache(String className) {
1143 return positiveLookupCache.get(className);
1144 }
1145
1146 public void generatePositiveLookupCache(Class<?>[] cls) {
1147 if (cls.length > 0) {
1148 for (Class<?> c : cls) {
1149 positiveLookupCache.put(c.getName(), c);
1150 }
1151 usePositiveCache = true;
1152 }
1153 }
1154 }
|