87 * directly to that class loader. If there isn't a module containing the
88 * package then it delegates the search to the parent class loader and if not
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 final URLClassPath ucp;
108
109
110 /**
111 * A module defined/loaded by a built-in class loader.
112 *
113 * A LoadedModule encapsulates a ModuleReference along with its CodeSource
114 * URL to avoid needing to create this URL when defining classes.
115 */
116 private static class LoadedModule {
117 private final BuiltinClassLoader loader;
118 private final ModuleReference mref;
119 private final URI uri; // may be null
120 private @Stable URL codeSourceURL; // may be null
121
122 LoadedModule(BuiltinClassLoader loader, ModuleReference mref) {
123 URL url = null;
124 this.uri = mref.location().orElse(null);
125
126 // for non-jrt schemes we need to resolve the codeSourceURL
127 // eagerly during bootstrap since the handler might be
128 // overridden
139 String name() { return mref.descriptor().name(); }
140
141 URL codeSourceURL() {
142 URL url = codeSourceURL;
143 if (url == null && uri != null) {
144 codeSourceURL = url = createURL(uri);
145 }
146 return url;
147 }
148
149 private URL createURL(URI uri) {
150 URL url = null;
151 try {
152 url = uri.toURL();
153 } catch (MalformedURLException | IllegalArgumentException e) {
154 }
155 return url;
156 }
157 }
158
159
160 // maps package name to loaded module for modules in the boot layer
161 private static final Map<String, LoadedModule> packageToModule
162 = new ConcurrentHashMap<>(1024);
163
164 // maps a module name to a module reference
165 private final Map<String, ModuleReference> nameToModule;
166
167 // maps a module reference to a module reader
168 private final Map<ModuleReference, ModuleReader> moduleToReader;
169
170 // cache of resource name -> list of URLs.
171 // used only for resources that are not in module packages
172 private volatile SoftReference<Map<String, List<URL>>> resourceCache;
173
174 /**
175 * Create a new instance.
176 */
177 BuiltinClassLoader(String name, BuiltinClassLoader parent, URLClassPath ucp) {
178 // ensure getParent() returns null when the parent is the boot loader
179 super(name, parent == null || parent == ClassLoaders.bootLoader() ? null : parent);
180
181 this.parent = parent;
182 this.ucp = ucp;
183
184 this.nameToModule = new ConcurrentHashMap<>(32);
185 this.moduleToReader = new ConcurrentHashMap<>();
186 }
187
188 /**
189 * Returns {@code true} if there is a class path associated with this
190 * class loader.
191 */
192 boolean hasClassPath() {
193 return ucp != null;
194 }
195
196 /**
197 * Register a module this class loader. This has the effect of making the
198 * types in the module visible.
199 */
200 public void loadModule(ModuleReference mref) {
201 ModuleDescriptor descriptor = mref.descriptor();
202 String mn = descriptor.name();
203 if (nameToModule.putIfAbsent(mn, mref) != null) {
204 throw new InternalError(mn + " already defined to this loader");
205 }
206
207 LoadedModule loadedModule = new LoadedModule(this, mref);
208 for (String pn : descriptor.packages()) {
1024 */
1025 private boolean isOpen(ModuleReference mref, String pn) {
1026 ModuleDescriptor descriptor = mref.descriptor();
1027 if (descriptor.isOpen() || descriptor.isAutomatic())
1028 return true;
1029 for (ModuleDescriptor.Opens opens : descriptor.opens()) {
1030 String source = opens.source();
1031 if (!opens.isQualified() && source.equals(pn)) {
1032 return true;
1033 }
1034 }
1035 return false;
1036 }
1037
1038 /**
1039 * Checks access to the given URL. We use URLClassPath for consistent
1040 * checking with java.net.URLClassLoader.
1041 */
1042 private static URL checkURL(URL url) {
1043 return URLClassPath.checkURL(url);
1044 }
1045 }
|
87 * directly to that class loader. If there isn't a module containing the
88 * package then it delegates the search to the parent class loader and if not
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
138 String name() { return mref.descriptor().name(); }
139
140 URL codeSourceURL() {
141 URL url = codeSourceURL;
142 if (url == null && uri != null) {
143 codeSourceURL = url = createURL(uri);
144 }
145 return url;
146 }
147
148 private URL createURL(URI uri) {
149 URL url = null;
150 try {
151 url = uri.toURL();
152 } catch (MalformedURLException | IllegalArgumentException e) {
153 }
154 return url;
155 }
156 }
157
158 // maps package name to loaded module for modules in the boot layer
159 private static final Map<String, LoadedModule> packageToModule;
160 static {
161 ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get();
162 if (archivedClassLoaders != null) {
163 @SuppressWarnings("unchecked")
164 Map<String, LoadedModule> map
165 = (Map<String, LoadedModule>) archivedClassLoaders.packageToModule();
166 packageToModule = map;
167 } else {
168 packageToModule = new ConcurrentHashMap<>(1024);
169 }
170 }
171
172 /**
173 * Invoked by ArchivedClassLoaders to archive the package-to-module map.
174 */
175 static Map<String, ?> packageToModule() {
176 return packageToModule;
177 }
178
179 // maps a module name to a module reference
180 private final Map<String, ModuleReference> nameToModule;
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.
221 */
222 boolean hasClassPath() {
223 return ucp != null;
224 }
225
226 /**
227 * Register a module this class loader. This has the effect of making the
228 * types in the module visible.
229 */
230 public void loadModule(ModuleReference mref) {
231 ModuleDescriptor descriptor = mref.descriptor();
232 String mn = descriptor.name();
233 if (nameToModule.putIfAbsent(mn, mref) != null) {
234 throw new InternalError(mn + " already defined to this loader");
235 }
236
237 LoadedModule loadedModule = new LoadedModule(this, mref);
238 for (String pn : descriptor.packages()) {
1054 */
1055 private boolean isOpen(ModuleReference mref, String pn) {
1056 ModuleDescriptor descriptor = mref.descriptor();
1057 if (descriptor.isOpen() || descriptor.isAutomatic())
1058 return true;
1059 for (ModuleDescriptor.Opens opens : descriptor.opens()) {
1060 String source = opens.source();
1061 if (!opens.isQualified() && source.equals(pn)) {
1062 return true;
1063 }
1064 }
1065 return false;
1066 }
1067
1068 /**
1069 * Checks access to the given URL. We use URLClassPath for consistent
1070 * checking with java.net.URLClassLoader.
1071 */
1072 private static URL checkURL(URL url) {
1073 return URLClassPath.checkURL(url);
1074 }
1075
1076 // Called from VM only, during -Xshare:dump
1077 private void resetArchivedStates() {
1078 ucp = null;
1079 }
1080 }
|