37 #include "classfile/vmSymbols.hpp"
38 #include "memory/allocation.inline.hpp"
39 #include "memory/filemap.hpp"
40 #include "memory/resourceArea.hpp"
41 #include "oops/instanceKlass.hpp"
42 #include "oops/oop.inline.hpp"
43 #include "oops/symbol.hpp"
44 #include "runtime/arguments.hpp"
45 #include "runtime/handles.inline.hpp"
46 #include "runtime/java.hpp"
47 #include "runtime/javaCalls.hpp"
48 #include "runtime/os.hpp"
49 #include "services/threadService.hpp"
50 #include "utilities/stringUtils.hpp"
51
52 jshort ClassLoaderExt::_app_class_paths_start_index = ClassLoaderExt::max_classpath_index;
53 jshort ClassLoaderExt::_app_module_paths_start_index = ClassLoaderExt::max_classpath_index;
54 bool ClassLoaderExt::_has_app_classes = false;
55 bool ClassLoaderExt::_has_platform_classes = false;
56
57 void ClassLoaderExt::setup_app_search_path() {
58 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump and -XX:+UseAppCDS");
59 _app_class_paths_start_index = ClassLoader::num_boot_classpath_entries();
60 char* app_class_path = os::strdup(Arguments::get_appclasspath());
61
62 if (strcmp(app_class_path, ".") == 0) {
63 // This doesn't make any sense, even for AppCDS, so let's skip it. We
64 // don't want to throw an error here because -cp "." is usually assigned
65 // by the launcher when classpath is not specified.
66 trace_class_path("app loader class path (skipped)=", app_class_path);
67 } else {
68 trace_class_path("app loader class path=", app_class_path);
69 shared_paths_misc_info()->add_app_classpath(app_class_path);
70 ClassLoader::setup_app_search_path(app_class_path);
71 }
72 }
73
74 void ClassLoaderExt::process_module_table(ModuleEntryTable* met, TRAPS) {
75 ResourceMark rm;
76 for (int i = 0; i < met->table_size(); i++) {
77 for (ModuleEntry* m = met->bucket(i); m != NULL;) {
78 char* path = m->location()->as_C_string();
79 if (strncmp(path, "file:", 5) == 0 && ClassLoader::string_ends_with(path, ".jar")) {
80 m->print();
81 path = ClassLoader::skip_uri_protocol(path);
82 ClassLoader::setup_module_search_path(path, THREAD);
83 }
84 m = m->next();
85 }
86 }
87 }
88 void ClassLoaderExt::setup_module_search_path(TRAPS) {
89 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump and -XX:+UseAppCDS");
90 _app_module_paths_start_index = ClassLoader::num_boot_classpath_entries() +
91 ClassLoader::num_app_classpath_entries();
92 Handle system_class_loader (THREAD, SystemDictionary::java_system_loader());
93 ModuleEntryTable* met = Modules::get_module_entry_table(system_class_loader);
94 process_module_table(met, THREAD);
95 }
96
97 char* ClassLoaderExt::read_manifest(ClassPathEntry* entry, jint *manifest_size, bool clean_text, TRAPS) {
98 const char* name = "META-INF/MANIFEST.MF";
99 char* manifest;
100 jint size;
101
102 assert(entry->is_jar_file(), "must be");
103 manifest = (char*) ((ClassPathZipEntry*)entry )->open_entry(name, &size, true, CHECK_NULL);
104
105 if (manifest == NULL) { // No Manifest
106 *manifest_size = 0;
107 return NULL;
108 }
109
198 file_end = end;
199 }
200
201 int name_len = (int)strlen(file_start);
202 if (name_len > 0) {
203 ResourceMark rm(THREAD);
204 char* libname = NEW_RESOURCE_ARRAY(char, dir_len + name_len + 1);
205 *libname = 0;
206 strncat(libname, dir_name, dir_len);
207 strncat(libname, file_start, name_len);
208 trace_class_path("library = ", libname);
209 ClassLoader::update_class_path_entry_list(libname, true, false);
210 }
211
212 file_start = file_end;
213 }
214 }
215 }
216
217 void ClassLoaderExt::setup_search_paths() {
218 if (UseAppCDS) {
219 shared_paths_misc_info()->record_app_offset();
220 ClassLoaderExt::setup_app_search_path();
221 }
222 }
223
224 void ClassLoaderExt::setup_module_paths(TRAPS) {
225 if (UseAppCDS) {
226 ClassLoaderExt::setup_module_search_path(THREAD);
227 }
228 }
229
230 Thread* ClassLoaderExt::Context::_dump_thread = NULL;
231
232 void ClassLoaderExt::record_result(ClassLoaderExt::Context *context,
233 Symbol* class_name,
234 const s2 classpath_index,
235 InstanceKlass* result,
236 TRAPS) {
237 assert(DumpSharedSpaces, "Sanity");
238
239 // We need to remember where the class comes from during dumping.
240 oop loader = result->class_loader();
241 s2 classloader_type = ClassLoader::BOOT_LOADER;
242 if (SystemDictionary::is_system_class_loader(loader)) {
243 classloader_type = ClassLoader::APP_LOADER;
244 ClassLoaderExt::set_has_app_classes();
245 } else if (SystemDictionary::is_platform_class_loader(loader)) {
246 classloader_type = ClassLoader::PLATFORM_LOADER;
247 ClassLoaderExt::set_has_platform_classes();
248 }
249 result->set_shared_classpath_index(classpath_index);
250 result->set_class_loader_type(classloader_type);
251 }
252
253 void ClassLoaderExt::finalize_shared_paths_misc_info() {
254 if (UseAppCDS) {
255 if (!_has_app_classes) {
256 shared_paths_misc_info()->pop_app();
257 }
258 }
259 }
260
261 // Load the class of the given name from the location given by path. The path is specified by
262 // the "source:" in the class list file (see classListParser.cpp), and can be a directory or
263 // a JAR file.
264 InstanceKlass* ClassLoaderExt::load_class(Symbol* name, const char* path, TRAPS) {
265
266 assert(name != NULL, "invariant");
267 assert(DumpSharedSpaces && UseAppCDS, "this function is only used with -Xshare:dump and -XX:+UseAppCDS");
268 ResourceMark rm(THREAD);
269 const char* class_name = name->as_C_string();
270
271 const char* file_name = file_name_for_class_name(class_name,
272 name->utf8_length());
273 assert(file_name != NULL, "invariant");
274
275 // Lookup stream for parsing .class file
276 ClassFileStream* stream = NULL;
277 ClassPathEntry* e = find_classpath_entry_from_cache(path, CHECK_NULL);
278 if (e == NULL) {
279 return NULL;
280 }
281 {
282 PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
283 ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(),
284 PerfClassTraceTime::CLASS_LOAD);
285 stream = e->open_stream(file_name, CHECK_NULL);
286 }
287
305 THREAD);
306
307 if (HAS_PENDING_EXCEPTION) {
308 tty->print_cr("Preload Error: Failed to load %s", class_name);
309 return NULL;
310 }
311 result->set_shared_classpath_index(UNREGISTERED_INDEX);
312 SystemDictionaryShared::set_shared_class_misc_info(result, stream);
313 return result;
314 }
315
316 struct CachedClassPathEntry {
317 const char* _path;
318 ClassPathEntry* _entry;
319 };
320
321 static GrowableArray<CachedClassPathEntry>* cached_path_entries = NULL;
322
323 ClassPathEntry* ClassLoaderExt::find_classpath_entry_from_cache(const char* path, TRAPS) {
324 // This is called from dump time so it's single threaded and there's no need for a lock.
325 assert(DumpSharedSpaces && UseAppCDS, "this function is only used with -Xshare:dump and -XX:+UseAppCDS");
326 if (cached_path_entries == NULL) {
327 cached_path_entries = new (ResourceObj::C_HEAP, mtClass) GrowableArray<CachedClassPathEntry>(20, /*c heap*/ true);
328 }
329 CachedClassPathEntry ccpe;
330 for (int i=0; i<cached_path_entries->length(); i++) {
331 ccpe = cached_path_entries->at(i);
332 if (strcmp(ccpe._path, path) == 0) {
333 if (i != 0) {
334 // Put recent entries at the beginning to speed up searches.
335 cached_path_entries->remove_at(i);
336 cached_path_entries->insert_before(0, ccpe);
337 }
338 return ccpe._entry;
339 }
340 }
341
342 struct stat st;
343 if (os::stat(path, &st) != 0) {
344 // File or directory not found
345 return NULL;
|
37 #include "classfile/vmSymbols.hpp"
38 #include "memory/allocation.inline.hpp"
39 #include "memory/filemap.hpp"
40 #include "memory/resourceArea.hpp"
41 #include "oops/instanceKlass.hpp"
42 #include "oops/oop.inline.hpp"
43 #include "oops/symbol.hpp"
44 #include "runtime/arguments.hpp"
45 #include "runtime/handles.inline.hpp"
46 #include "runtime/java.hpp"
47 #include "runtime/javaCalls.hpp"
48 #include "runtime/os.hpp"
49 #include "services/threadService.hpp"
50 #include "utilities/stringUtils.hpp"
51
52 jshort ClassLoaderExt::_app_class_paths_start_index = ClassLoaderExt::max_classpath_index;
53 jshort ClassLoaderExt::_app_module_paths_start_index = ClassLoaderExt::max_classpath_index;
54 bool ClassLoaderExt::_has_app_classes = false;
55 bool ClassLoaderExt::_has_platform_classes = false;
56
57 void ClassLoaderExt::append_boot_classpath(ClassPathEntry* new_entry) {
58 #if INCLUDE_CDS
59 warning("Sharing is only supported for boot loader classes because bootstrap classpath has been appended");
60 FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header();
61 header->set_has_platform_or_app_classes(false);
62 #endif
63 ClassLoader::add_to_boot_append_entries(new_entry);
64 }
65
66 void ClassLoaderExt::setup_app_search_path() {
67 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
68 _app_class_paths_start_index = ClassLoader::num_boot_classpath_entries();
69 char* app_class_path = os::strdup(Arguments::get_appclasspath());
70
71 if (strcmp(app_class_path, ".") == 0) {
72 // This doesn't make any sense, even for AppCDS, so let's skip it. We
73 // don't want to throw an error here because -cp "." is usually assigned
74 // by the launcher when classpath is not specified.
75 trace_class_path("app loader class path (skipped)=", app_class_path);
76 } else {
77 trace_class_path("app loader class path=", app_class_path);
78 shared_paths_misc_info()->add_app_classpath(app_class_path);
79 ClassLoader::setup_app_search_path(app_class_path);
80 }
81 }
82
83 void ClassLoaderExt::process_module_table(ModuleEntryTable* met, TRAPS) {
84 ResourceMark rm;
85 for (int i = 0; i < met->table_size(); i++) {
86 for (ModuleEntry* m = met->bucket(i); m != NULL;) {
87 char* path = m->location()->as_C_string();
88 if (strncmp(path, "file:", 5) == 0 && ClassLoader::string_ends_with(path, ".jar")) {
89 m->print();
90 path = ClassLoader::skip_uri_protocol(path);
91 ClassLoader::setup_module_search_path(path, THREAD);
92 }
93 m = m->next();
94 }
95 }
96 }
97 void ClassLoaderExt::setup_module_paths(TRAPS) {
98 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
99 _app_module_paths_start_index = ClassLoader::num_boot_classpath_entries() +
100 ClassLoader::num_app_classpath_entries();
101 Handle system_class_loader (THREAD, SystemDictionary::java_system_loader());
102 ModuleEntryTable* met = Modules::get_module_entry_table(system_class_loader);
103 process_module_table(met, THREAD);
104 }
105
106 char* ClassLoaderExt::read_manifest(ClassPathEntry* entry, jint *manifest_size, bool clean_text, TRAPS) {
107 const char* name = "META-INF/MANIFEST.MF";
108 char* manifest;
109 jint size;
110
111 assert(entry->is_jar_file(), "must be");
112 manifest = (char*) ((ClassPathZipEntry*)entry )->open_entry(name, &size, true, CHECK_NULL);
113
114 if (manifest == NULL) { // No Manifest
115 *manifest_size = 0;
116 return NULL;
117 }
118
207 file_end = end;
208 }
209
210 int name_len = (int)strlen(file_start);
211 if (name_len > 0) {
212 ResourceMark rm(THREAD);
213 char* libname = NEW_RESOURCE_ARRAY(char, dir_len + name_len + 1);
214 *libname = 0;
215 strncat(libname, dir_name, dir_len);
216 strncat(libname, file_start, name_len);
217 trace_class_path("library = ", libname);
218 ClassLoader::update_class_path_entry_list(libname, true, false);
219 }
220
221 file_start = file_end;
222 }
223 }
224 }
225
226 void ClassLoaderExt::setup_search_paths() {
227 shared_paths_misc_info()->record_app_offset();
228 ClassLoaderExt::setup_app_search_path();
229 }
230
231 Thread* ClassLoaderExt::Context::_dump_thread = NULL;
232
233 void ClassLoaderExt::record_result(ClassLoaderExt::Context *context,
234 Symbol* class_name,
235 const s2 classpath_index,
236 InstanceKlass* result,
237 TRAPS) {
238 assert(DumpSharedSpaces, "Sanity");
239
240 // We need to remember where the class comes from during dumping.
241 oop loader = result->class_loader();
242 s2 classloader_type = ClassLoader::BOOT_LOADER;
243 if (SystemDictionary::is_system_class_loader(loader)) {
244 classloader_type = ClassLoader::APP_LOADER;
245 ClassLoaderExt::set_has_app_classes();
246 } else if (SystemDictionary::is_platform_class_loader(loader)) {
247 classloader_type = ClassLoader::PLATFORM_LOADER;
248 ClassLoaderExt::set_has_platform_classes();
249 }
250 result->set_shared_classpath_index(classpath_index);
251 result->set_class_loader_type(classloader_type);
252 }
253
254 void ClassLoaderExt::finalize_shared_paths_misc_info() {
255 if (!_has_app_classes) {
256 shared_paths_misc_info()->pop_app();
257 }
258 }
259
260 // Load the class of the given name from the location given by path. The path is specified by
261 // the "source:" in the class list file (see classListParser.cpp), and can be a directory or
262 // a JAR file.
263 InstanceKlass* ClassLoaderExt::load_class(Symbol* name, const char* path, TRAPS) {
264
265 assert(name != NULL, "invariant");
266 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
267 ResourceMark rm(THREAD);
268 const char* class_name = name->as_C_string();
269
270 const char* file_name = file_name_for_class_name(class_name,
271 name->utf8_length());
272 assert(file_name != NULL, "invariant");
273
274 // Lookup stream for parsing .class file
275 ClassFileStream* stream = NULL;
276 ClassPathEntry* e = find_classpath_entry_from_cache(path, CHECK_NULL);
277 if (e == NULL) {
278 return NULL;
279 }
280 {
281 PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
282 ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(),
283 PerfClassTraceTime::CLASS_LOAD);
284 stream = e->open_stream(file_name, CHECK_NULL);
285 }
286
304 THREAD);
305
306 if (HAS_PENDING_EXCEPTION) {
307 tty->print_cr("Preload Error: Failed to load %s", class_name);
308 return NULL;
309 }
310 result->set_shared_classpath_index(UNREGISTERED_INDEX);
311 SystemDictionaryShared::set_shared_class_misc_info(result, stream);
312 return result;
313 }
314
315 struct CachedClassPathEntry {
316 const char* _path;
317 ClassPathEntry* _entry;
318 };
319
320 static GrowableArray<CachedClassPathEntry>* cached_path_entries = NULL;
321
322 ClassPathEntry* ClassLoaderExt::find_classpath_entry_from_cache(const char* path, TRAPS) {
323 // This is called from dump time so it's single threaded and there's no need for a lock.
324 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
325 if (cached_path_entries == NULL) {
326 cached_path_entries = new (ResourceObj::C_HEAP, mtClass) GrowableArray<CachedClassPathEntry>(20, /*c heap*/ true);
327 }
328 CachedClassPathEntry ccpe;
329 for (int i=0; i<cached_path_entries->length(); i++) {
330 ccpe = cached_path_entries->at(i);
331 if (strcmp(ccpe._path, path) == 0) {
332 if (i != 0) {
333 // Put recent entries at the beginning to speed up searches.
334 cached_path_entries->remove_at(i);
335 cached_path_entries->insert_before(0, ccpe);
336 }
337 return ccpe._entry;
338 }
339 }
340
341 struct stat st;
342 if (os::stat(path, &st) != 0) {
343 // File or directory not found
344 return NULL;
|