Mercurial > hg > truffle
comparison src/share/vm/classfile/classLoader.cpp @ 20375:6e0cb14ce59b
8046070: Class Data Sharing clean up and refactoring
Summary: Cleaned up CDS to be more configurable, maintainable and extensible
Reviewed-by: dholmes, coleenp, acorn, mchung
author | iklam |
---|---|
date | Thu, 21 Aug 2014 13:57:51 -0700 |
parents | 78bbf4d43a14 |
children | bb239308be67 |
comparison
equal
deleted
inserted
replaced
20374:999824269b71 | 20375:6e0cb14ce59b |
---|---|
24 | 24 |
25 #include "precompiled.hpp" | 25 #include "precompiled.hpp" |
26 #include "classfile/classFileParser.hpp" | 26 #include "classfile/classFileParser.hpp" |
27 #include "classfile/classFileStream.hpp" | 27 #include "classfile/classFileStream.hpp" |
28 #include "classfile/classLoader.hpp" | 28 #include "classfile/classLoader.hpp" |
29 #include "classfile/classLoaderExt.hpp" | |
29 #include "classfile/classLoaderData.inline.hpp" | 30 #include "classfile/classLoaderData.inline.hpp" |
30 #include "classfile/javaClasses.hpp" | 31 #include "classfile/javaClasses.hpp" |
32 #if INCLUDE_CDS | |
33 #include "classfile/sharedPathsMiscInfo.hpp" | |
34 #include "classfile/sharedClassUtil.hpp" | |
35 #endif | |
31 #include "classfile/systemDictionary.hpp" | 36 #include "classfile/systemDictionary.hpp" |
32 #include "classfile/vmSymbols.hpp" | 37 #include "classfile/vmSymbols.hpp" |
33 #include "compiler/compileBroker.hpp" | 38 #include "compiler/compileBroker.hpp" |
34 #include "gc_interface/collectedHeap.inline.hpp" | 39 #include "gc_interface/collectedHeap.inline.hpp" |
35 #include "interpreter/bytecodeStream.hpp" | 40 #include "interpreter/bytecodeStream.hpp" |
36 #include "interpreter/oopMapCache.hpp" | 41 #include "interpreter/oopMapCache.hpp" |
37 #include "memory/allocation.inline.hpp" | 42 #include "memory/allocation.inline.hpp" |
43 #include "memory/filemap.hpp" | |
38 #include "memory/generation.hpp" | 44 #include "memory/generation.hpp" |
39 #include "memory/oopFactory.hpp" | 45 #include "memory/oopFactory.hpp" |
40 #include "memory/universe.inline.hpp" | 46 #include "memory/universe.inline.hpp" |
41 #include "oops/instanceKlass.hpp" | 47 #include "oops/instanceKlass.hpp" |
42 #include "oops/instanceRefKlass.hpp" | 48 #include "oops/instanceRefKlass.hpp" |
127 PerfCounter* ClassLoader::_isUnsyncloadClass = NULL; | 133 PerfCounter* ClassLoader::_isUnsyncloadClass = NULL; |
128 PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL; | 134 PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL; |
129 | 135 |
130 ClassPathEntry* ClassLoader::_first_entry = NULL; | 136 ClassPathEntry* ClassLoader::_first_entry = NULL; |
131 ClassPathEntry* ClassLoader::_last_entry = NULL; | 137 ClassPathEntry* ClassLoader::_last_entry = NULL; |
138 int ClassLoader::_num_entries = 0; | |
132 PackageHashtable* ClassLoader::_package_hash_table = NULL; | 139 PackageHashtable* ClassLoader::_package_hash_table = NULL; |
133 | 140 |
141 #if INCLUDE_CDS | |
142 SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL; | |
143 #endif | |
134 // helper routines | 144 // helper routines |
135 bool string_starts_with(const char* str, const char* str_to_find) { | 145 bool string_starts_with(const char* str, const char* str_to_find) { |
136 size_t str_len = strlen(str); | 146 size_t str_len = strlen(str); |
137 size_t str_to_find_len = strlen(str_to_find); | 147 size_t str_to_find_len = strlen(str_to_find); |
138 if (str_to_find_len > str_len) { | 148 if (str_to_find_len > str_len) { |
207 return NULL; | 217 return NULL; |
208 } | 218 } |
209 // check if file exists | 219 // check if file exists |
210 struct stat st; | 220 struct stat st; |
211 if (os::stat(path, &st) == 0) { | 221 if (os::stat(path, &st) == 0) { |
222 #if INCLUDE_CDS | |
223 if (DumpSharedSpaces) { | |
224 // We have already check in ClassLoader::check_shared_classpath() that the directory is empty, so | |
225 // we should never find a file underneath it -- unless user has added a new file while we are running | |
226 // the dump, in which case let's quit! | |
227 ShouldNotReachHere(); | |
228 } | |
229 #endif | |
212 // found file, open it | 230 // found file, open it |
213 int file_handle = os::open(path, 0, 0); | 231 int file_handle = os::open(path, 0, 0); |
214 if (file_handle != -1) { | 232 if (file_handle != -1) { |
215 // read contents into resource array | 233 // read contents into resource array |
216 u1* buffer = NEW_RESOURCE_ARRAY(u1, st.st_size); | 234 u1* buffer = NEW_RESOURCE_ARRAY(u1, st.st_size); |
241 (*ZipClose)(_zip); | 259 (*ZipClose)(_zip); |
242 } | 260 } |
243 FREE_C_HEAP_ARRAY(char, _zip_name, mtClass); | 261 FREE_C_HEAP_ARRAY(char, _zip_name, mtClass); |
244 } | 262 } |
245 | 263 |
246 ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) { | 264 u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) { |
247 // enable call to C land | 265 // enable call to C land |
248 JavaThread* thread = JavaThread::current(); | 266 JavaThread* thread = JavaThread::current(); |
249 ThreadToNativeFromVM ttn(thread); | 267 ThreadToNativeFromVM ttn(thread); |
250 // check whether zip archive contains name | 268 // check whether zip archive contains name |
251 jint filesize, name_len; | 269 jint name_len; |
252 jzentry* entry = (*FindEntry)(_zip, name, &filesize, &name_len); | 270 jzentry* entry = (*FindEntry)(_zip, name, filesize, &name_len); |
253 if (entry == NULL) return NULL; | 271 if (entry == NULL) return NULL; |
254 u1* buffer; | 272 u1* buffer; |
255 char name_buf[128]; | 273 char name_buf[128]; |
256 char* filename; | 274 char* filename; |
257 if (name_len < 128) { | 275 if (name_len < 128) { |
258 filename = name_buf; | 276 filename = name_buf; |
259 } else { | 277 } else { |
260 filename = NEW_RESOURCE_ARRAY(char, name_len + 1); | 278 filename = NEW_RESOURCE_ARRAY(char, name_len + 1); |
261 } | 279 } |
262 | 280 |
263 // file found, get pointer to class in mmaped jar file. | 281 // file found, get pointer to the entry in mmapped jar file. |
264 if (ReadMappedEntry == NULL || | 282 if (ReadMappedEntry == NULL || |
265 !(*ReadMappedEntry)(_zip, entry, &buffer, filename)) { | 283 !(*ReadMappedEntry)(_zip, entry, &buffer, filename)) { |
266 // mmaped access not available, perhaps due to compression, | 284 // mmapped access not available, perhaps due to compression, |
267 // read contents into resource array | 285 // read contents into resource array |
268 buffer = NEW_RESOURCE_ARRAY(u1, filesize); | 286 int size = (*filesize) + ((nul_terminate) ? 1 : 0); |
287 buffer = NEW_RESOURCE_ARRAY(u1, size); | |
269 if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL; | 288 if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL; |
289 } | |
290 | |
291 // return result | |
292 if (nul_terminate) { | |
293 buffer[*filesize] = 0; | |
294 } | |
295 return buffer; | |
296 } | |
297 | |
298 ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) { | |
299 jint filesize; | |
300 u1* buffer = open_entry(name, &filesize, false, CHECK_NULL); | |
301 if (buffer == NULL) { | |
302 return NULL; | |
270 } | 303 } |
271 if (UsePerfData) { | 304 if (UsePerfData) { |
272 ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize); | 305 ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize); |
273 } | 306 } |
274 // return result | 307 return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated |
275 return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated | |
276 } | 308 } |
277 | 309 |
278 // invoke function for each entry in the zip file | 310 // invoke function for each entry in the zip file |
279 void ClassPathZipEntry::contents_do(void f(const char* name, void* context), void* context) { | 311 void ClassPathZipEntry::contents_do(void f(const char* name, void* context), void* context) { |
280 JavaThread* thread = JavaThread::current(); | 312 JavaThread* thread = JavaThread::current(); |
285 if (ze == NULL) break; | 317 if (ze == NULL) break; |
286 (*f)(ze->name, context); | 318 (*f)(ze->name, context); |
287 } | 319 } |
288 } | 320 } |
289 | 321 |
290 LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st) : ClassPathEntry() { | 322 LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st, bool throw_exception) : ClassPathEntry() { |
291 _path = strdup(path); | 323 _path = strdup(path); |
292 _st = *st; | 324 _st = *st; |
293 _meta_index = NULL; | 325 _meta_index = NULL; |
294 _resolved_entry = NULL; | 326 _resolved_entry = NULL; |
295 _has_error = false; | 327 _has_error = false; |
328 _throw_exception = throw_exception; | |
296 } | 329 } |
297 | 330 |
298 bool LazyClassPathEntry::is_jar_file() { | 331 bool LazyClassPathEntry::is_jar_file() { |
299 return ((_st.st_mode & S_IFREG) == S_IFREG); | 332 return ((_st.st_mode & S_IFREG) == S_IFREG); |
300 } | 333 } |
302 ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) { | 335 ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) { |
303 if (_resolved_entry != NULL) { | 336 if (_resolved_entry != NULL) { |
304 return (ClassPathEntry*) _resolved_entry; | 337 return (ClassPathEntry*) _resolved_entry; |
305 } | 338 } |
306 ClassPathEntry* new_entry = NULL; | 339 ClassPathEntry* new_entry = NULL; |
307 new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, CHECK_NULL); | 340 new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, _throw_exception, CHECK_NULL); |
341 if (!_throw_exception && new_entry == NULL) { | |
342 assert(!HAS_PENDING_EXCEPTION, "must be"); | |
343 return NULL; | |
344 } | |
308 { | 345 { |
309 ThreadCritical tc; | 346 ThreadCritical tc; |
310 if (_resolved_entry == NULL) { | 347 if (_resolved_entry == NULL) { |
311 _resolved_entry = new_entry; | 348 _resolved_entry = new_entry; |
312 return new_entry; | 349 return new_entry; |
336 | 373 |
337 bool LazyClassPathEntry::is_lazy() { | 374 bool LazyClassPathEntry::is_lazy() { |
338 return true; | 375 return true; |
339 } | 376 } |
340 | 377 |
378 u1* LazyClassPathEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) { | |
379 if (_has_error) { | |
380 return NULL; | |
381 } | |
382 ClassPathEntry* cpe = resolve_entry(THREAD); | |
383 if (cpe == NULL) { | |
384 _has_error = true; | |
385 return NULL; | |
386 } else if (cpe->is_jar_file()) { | |
387 return ((ClassPathZipEntry*)cpe)->open_entry(name, filesize, nul_terminate,THREAD); | |
388 } else { | |
389 ShouldNotReachHere(); | |
390 *filesize = 0; | |
391 return NULL; | |
392 } | |
393 } | |
394 | |
341 static void print_meta_index(LazyClassPathEntry* entry, | 395 static void print_meta_index(LazyClassPathEntry* entry, |
342 GrowableArray<char*>& meta_packages) { | 396 GrowableArray<char*>& meta_packages) { |
343 tty->print("[Meta index for %s=", entry->name()); | 397 tty->print("[Meta index for %s=", entry->name()); |
344 for (int i = 0; i < meta_packages.length(); i++) { | 398 for (int i = 0; i < meta_packages.length(); i++) { |
345 if (i > 0) tty->print(" "); | 399 if (i > 0) tty->print(" "); |
346 tty->print("%s", meta_packages.at(i)); | 400 tty->print("%s", meta_packages.at(i)); |
347 } | 401 } |
348 tty->print_cr("]"); | 402 tty->print_cr("]"); |
349 } | 403 } |
350 | 404 |
351 | 405 #if INCLUDE_CDS |
352 void ClassLoader::setup_meta_index() { | 406 void ClassLoader::exit_with_path_failure(const char* error, const char* message) { |
407 assert(DumpSharedSpaces, "only called at dump time"); | |
408 tty->print_cr("Hint: enable -XX:+TraceClassPaths to diagnose the failure"); | |
409 vm_exit_during_initialization(error, message); | |
410 } | |
411 #endif | |
412 | |
413 void ClassLoader::trace_class_path(const char* msg, const char* name) { | |
414 if (!TraceClassPaths) { | |
415 return; | |
416 } | |
417 | |
418 if (msg) { | |
419 tty->print("%s", msg); | |
420 } | |
421 if (name) { | |
422 if (strlen(name) < 256) { | |
423 tty->print("%s", name); | |
424 } else { | |
425 // For very long paths, we need to print each character separately, | |
426 // as print_cr() has a length limit | |
427 while (name[0] != '\0') { | |
428 tty->print("%c", name[0]); | |
429 name++; | |
430 } | |
431 } | |
432 } | |
433 if (msg && msg[0] == '[') { | |
434 tty->print_cr("]"); | |
435 } else { | |
436 tty->cr(); | |
437 } | |
438 } | |
439 | |
440 void ClassLoader::setup_bootstrap_meta_index() { | |
353 // Set up meta index which allows us to open boot jars lazily if | 441 // Set up meta index which allows us to open boot jars lazily if |
354 // class data sharing is enabled | 442 // class data sharing is enabled |
443 const char* meta_index_path = Arguments::get_meta_index_path(); | |
444 const char* meta_index_dir = Arguments::get_meta_index_dir(); | |
445 setup_meta_index(meta_index_path, meta_index_dir, 0); | |
446 } | |
447 | |
448 void ClassLoader::setup_meta_index(const char* meta_index_path, const char* meta_index_dir, int start_index) { | |
355 const char* known_version = "% VERSION 2"; | 449 const char* known_version = "% VERSION 2"; |
356 char* meta_index_path = Arguments::get_meta_index_path(); | |
357 char* meta_index_dir = Arguments::get_meta_index_dir(); | |
358 FILE* file = fopen(meta_index_path, "r"); | 450 FILE* file = fopen(meta_index_path, "r"); |
359 int line_no = 0; | 451 int line_no = 0; |
452 #if INCLUDE_CDS | |
453 if (DumpSharedSpaces) { | |
454 if (file != NULL) { | |
455 _shared_paths_misc_info->add_required_file(meta_index_path); | |
456 } else { | |
457 _shared_paths_misc_info->add_nonexist_path(meta_index_path); | |
458 } | |
459 } | |
460 #endif | |
360 if (file != NULL) { | 461 if (file != NULL) { |
361 ResourceMark rm; | 462 ResourceMark rm; |
362 LazyClassPathEntry* cur_entry = NULL; | 463 LazyClassPathEntry* cur_entry = NULL; |
363 GrowableArray<char*> boot_class_path_packages(10); | 464 GrowableArray<char*> boot_class_path_packages(10); |
364 char package_name[256]; | 465 char package_name[256]; |
389 case '@': | 490 case '@': |
390 { | 491 { |
391 // Hand off current packages to current lazy entry (if any) | 492 // Hand off current packages to current lazy entry (if any) |
392 if ((cur_entry != NULL) && | 493 if ((cur_entry != NULL) && |
393 (boot_class_path_packages.length() > 0)) { | 494 (boot_class_path_packages.length() > 0)) { |
394 if (TraceClassLoading && Verbose) { | 495 if ((TraceClassLoading || TraceClassPaths) && Verbose) { |
395 print_meta_index(cur_entry, boot_class_path_packages); | 496 print_meta_index(cur_entry, boot_class_path_packages); |
396 } | 497 } |
397 MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), | 498 MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), |
398 boot_class_path_packages.length()); | 499 boot_class_path_packages.length()); |
399 cur_entry->set_meta_index(index); | 500 cur_entry->set_meta_index(index); |
400 } | 501 } |
401 cur_entry = NULL; | 502 cur_entry = NULL; |
402 boot_class_path_packages.clear(); | 503 boot_class_path_packages.clear(); |
403 | 504 |
404 // Find lazy entry corresponding to this jar file | 505 // Find lazy entry corresponding to this jar file |
405 for (ClassPathEntry* entry = _first_entry; entry != NULL; entry = entry->next()) { | 506 int count = 0; |
406 if (entry->is_lazy() && | 507 for (ClassPathEntry* entry = _first_entry; entry != NULL; entry = entry->next(), count++) { |
508 if (count >= start_index && | |
509 entry->is_lazy() && | |
407 string_starts_with(entry->name(), meta_index_dir) && | 510 string_starts_with(entry->name(), meta_index_dir) && |
408 string_ends_with(entry->name(), &package_name[2])) { | 511 string_ends_with(entry->name(), &package_name[2])) { |
409 cur_entry = (LazyClassPathEntry*) entry; | 512 cur_entry = (LazyClassPathEntry*) entry; |
410 break; | 513 break; |
411 } | 514 } |
438 } | 541 } |
439 } | 542 } |
440 // Hand off current packages to current lazy entry (if any) | 543 // Hand off current packages to current lazy entry (if any) |
441 if ((cur_entry != NULL) && | 544 if ((cur_entry != NULL) && |
442 (boot_class_path_packages.length() > 0)) { | 545 (boot_class_path_packages.length() > 0)) { |
443 if (TraceClassLoading && Verbose) { | 546 if ((TraceClassLoading || TraceClassPaths) && Verbose) { |
444 print_meta_index(cur_entry, boot_class_path_packages); | 547 print_meta_index(cur_entry, boot_class_path_packages); |
445 } | 548 } |
446 MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), | 549 MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), |
447 boot_class_path_packages.length()); | 550 boot_class_path_packages.length()); |
448 cur_entry->set_meta_index(index); | 551 cur_entry->set_meta_index(index); |
449 } | 552 } |
450 fclose(file); | 553 fclose(file); |
451 } | 554 } |
452 } | 555 } |
453 | 556 |
557 #if INCLUDE_CDS | |
558 void ClassLoader::check_shared_classpath(const char *path) { | |
559 if (strcmp(path, "") == 0) { | |
560 exit_with_path_failure("Cannot have empty path in archived classpaths", NULL); | |
561 } | |
562 | |
563 struct stat st; | |
564 if (os::stat(path, &st) == 0) { | |
565 if ((st.st_mode & S_IFREG) != S_IFREG) { // is directory | |
566 if (!os::dir_is_empty(path)) { | |
567 tty->print_cr("Error: non-empty directory '%s'", path); | |
568 exit_with_path_failure("CDS allows only empty directories in archived classpaths", NULL); | |
569 } | |
570 } | |
571 } | |
572 } | |
573 #endif | |
574 | |
454 void ClassLoader::setup_bootstrap_search_path() { | 575 void ClassLoader::setup_bootstrap_search_path() { |
455 assert(_first_entry == NULL, "should not setup bootstrap class search path twice"); | 576 assert(_first_entry == NULL, "should not setup bootstrap class search path twice"); |
456 char* sys_class_path = os::strdup(Arguments::get_sysclasspath()); | 577 char* sys_class_path = os::strdup(Arguments::get_sysclasspath()); |
457 if (TraceClassLoading && Verbose) { | 578 if (!PrintSharedArchiveAndExit) { |
458 tty->print_cr("[Bootstrap loader class path=%s]", sys_class_path); | 579 trace_class_path("[Bootstrap loader class path=", sys_class_path); |
459 } | 580 } |
460 | 581 #if INCLUDE_CDS |
461 int len = (int)strlen(sys_class_path); | 582 if (DumpSharedSpaces) { |
583 _shared_paths_misc_info->add_boot_classpath(Arguments::get_sysclasspath()); | |
584 } | |
585 #endif | |
586 setup_search_path(sys_class_path); | |
587 os::free(sys_class_path); | |
588 } | |
589 | |
590 #if INCLUDE_CDS | |
591 int ClassLoader::get_shared_paths_misc_info_size() { | |
592 return _shared_paths_misc_info->get_used_bytes(); | |
593 } | |
594 | |
595 void* ClassLoader::get_shared_paths_misc_info() { | |
596 return _shared_paths_misc_info->buffer(); | |
597 } | |
598 | |
599 bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) { | |
600 SharedPathsMiscInfo* checker = SharedClassUtil::allocate_shared_paths_misc_info((char*)buf, size); | |
601 bool result = checker->check(); | |
602 delete checker; | |
603 return result; | |
604 } | |
605 #endif | |
606 | |
607 void ClassLoader::setup_search_path(char *class_path) { | |
608 int offset = 0; | |
609 int len = (int)strlen(class_path); | |
462 int end = 0; | 610 int end = 0; |
463 | 611 |
464 // Iterate over class path entries | 612 // Iterate over class path entries |
465 for (int start = 0; start < len; start = end) { | 613 for (int start = 0; start < len; start = end) { |
466 while (sys_class_path[end] && sys_class_path[end] != os::path_separator()[0]) { | 614 while (class_path[end] && class_path[end] != os::path_separator()[0]) { |
467 end++; | 615 end++; |
468 } | 616 } |
469 char* path = NEW_C_HEAP_ARRAY(char, end-start+1, mtClass); | 617 EXCEPTION_MARK; |
470 strncpy(path, &sys_class_path[start], end-start); | 618 ResourceMark rm(THREAD); |
471 path[end-start] = '\0'; | 619 char* path = NEW_RESOURCE_ARRAY(char, end - start + 1); |
620 strncpy(path, &class_path[start], end - start); | |
621 path[end - start] = '\0'; | |
472 update_class_path_entry_list(path, false); | 622 update_class_path_entry_list(path, false); |
473 FREE_C_HEAP_ARRAY(char, path, mtClass); | 623 #if INCLUDE_CDS |
474 while (sys_class_path[end] == os::path_separator()[0]) { | 624 if (DumpSharedSpaces) { |
625 check_shared_classpath(path); | |
626 } | |
627 #endif | |
628 while (class_path[end] == os::path_separator()[0]) { | |
475 end++; | 629 end++; |
476 } | 630 } |
477 } | 631 } |
478 } | 632 } |
479 | 633 |
480 ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, bool lazy, TRAPS) { | 634 ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, |
635 bool lazy, bool throw_exception, TRAPS) { | |
481 JavaThread* thread = JavaThread::current(); | 636 JavaThread* thread = JavaThread::current(); |
482 if (lazy) { | 637 if (lazy) { |
483 return new LazyClassPathEntry(path, st); | 638 return new LazyClassPathEntry(path, st, throw_exception); |
484 } | 639 } |
485 ClassPathEntry* new_entry = NULL; | 640 ClassPathEntry* new_entry = NULL; |
486 if ((st->st_mode & S_IFREG) == S_IFREG) { | 641 if ((st->st_mode & S_IFREG) == S_IFREG) { |
487 // Regular file, should be a zip file | 642 // Regular file, should be a zip file |
488 // Canonicalized filename | 643 // Canonicalized filename |
489 char canonical_path[JVM_MAXPATHLEN]; | 644 char canonical_path[JVM_MAXPATHLEN]; |
490 if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { | 645 if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { |
491 // This matches the classic VM | 646 // This matches the classic VM |
492 THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL); | 647 if (throw_exception) { |
648 THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL); | |
649 } else { | |
650 return NULL; | |
651 } | |
493 } | 652 } |
494 char* error_msg = NULL; | 653 char* error_msg = NULL; |
495 jzfile* zip; | 654 jzfile* zip; |
496 { | 655 { |
497 // enable call to C land | 656 // enable call to C land |
499 HandleMark hm(thread); | 658 HandleMark hm(thread); |
500 zip = (*ZipOpen)(canonical_path, &error_msg); | 659 zip = (*ZipOpen)(canonical_path, &error_msg); |
501 } | 660 } |
502 if (zip != NULL && error_msg == NULL) { | 661 if (zip != NULL && error_msg == NULL) { |
503 new_entry = new ClassPathZipEntry(zip, path); | 662 new_entry = new ClassPathZipEntry(zip, path); |
504 if (TraceClassLoading) { | 663 if (TraceClassLoading || TraceClassPaths) { |
505 tty->print_cr("[Opened %s]", path); | 664 tty->print_cr("[Opened %s]", path); |
506 } | 665 } |
507 } else { | 666 } else { |
508 ResourceMark rm(thread); | 667 ResourceMark rm(thread); |
509 char *msg; | 668 char *msg; |
513 } else { | 672 } else { |
514 int len = (int)(strlen(path) + strlen(error_msg) + 128); | 673 int len = (int)(strlen(path) + strlen(error_msg) + 128); |
515 msg = NEW_RESOURCE_ARRAY(char, len); ; | 674 msg = NEW_RESOURCE_ARRAY(char, len); ; |
516 jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); | 675 jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); |
517 } | 676 } |
518 THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL); | 677 if (throw_exception) { |
678 THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL); | |
679 } else { | |
680 return NULL; | |
681 } | |
519 } | 682 } |
520 } else { | 683 } else { |
521 // Directory | 684 // Directory |
522 new_entry = new ClassPathDirEntry(path); | 685 new_entry = new ClassPathDirEntry(path); |
523 if (TraceClassLoading) { | 686 if (TraceClassLoading || TraceClassPaths) { |
524 tty->print_cr("[Path %s]", path); | 687 tty->print_cr("[Path %s]", path); |
525 } | 688 } |
526 } | 689 } |
527 return new_entry; | 690 return new_entry; |
528 } | 691 } |
579 } else { | 742 } else { |
580 _last_entry->set_next(new_entry); | 743 _last_entry->set_next(new_entry); |
581 _last_entry = new_entry; | 744 _last_entry = new_entry; |
582 } | 745 } |
583 } | 746 } |
584 } | 747 _num_entries ++; |
585 | 748 } |
586 void ClassLoader::update_class_path_entry_list(char *path, | 749 |
587 bool check_for_duplicates) { | 750 // Returns true IFF the file/dir exists and the entry was successfully created. |
751 bool ClassLoader::update_class_path_entry_list(char *path, | |
752 bool check_for_duplicates, | |
753 bool throw_exception) { | |
588 struct stat st; | 754 struct stat st; |
589 if (os::stat(path, &st) == 0) { | 755 if (os::stat(path, &st) == 0) { |
590 // File or directory found | 756 // File or directory found |
591 ClassPathEntry* new_entry = NULL; | 757 ClassPathEntry* new_entry = NULL; |
592 Thread* THREAD = Thread::current(); | 758 Thread* THREAD = Thread::current(); |
593 new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, CHECK); | 759 new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, throw_exception, CHECK_(false)); |
760 if (new_entry == NULL) { | |
761 return false; | |
762 } | |
594 // The kernel VM adds dynamically to the end of the classloader path and | 763 // The kernel VM adds dynamically to the end of the classloader path and |
595 // doesn't reorder the bootclasspath which would break java.lang.Package | 764 // doesn't reorder the bootclasspath which would break java.lang.Package |
596 // (see PackageInfo). | 765 // (see PackageInfo). |
597 // Add new entry to linked list | 766 // Add new entry to linked list |
598 if (!check_for_duplicates || !contains_entry(new_entry)) { | 767 if (!check_for_duplicates || !contains_entry(new_entry)) { |
599 add_to_list(new_entry); | 768 ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry); |
600 } | 769 } |
770 return true; | |
771 } else { | |
772 #if INCLUDE_CDS | |
773 if (DumpSharedSpaces) { | |
774 _shared_paths_misc_info->add_nonexist_path(path); | |
775 } | |
776 return false; | |
777 #endif | |
601 } | 778 } |
602 } | 779 } |
603 | 780 |
604 void ClassLoader::print_bootclasspath() { | 781 void ClassLoader::print_bootclasspath() { |
605 ClassPathEntry* e = _first_entry; | 782 ClassPathEntry* e = _first_entry; |
747 } | 924 } |
748 } | 925 } |
749 assert(n == number_of_entries(), "just checking"); | 926 assert(n == number_of_entries(), "just checking"); |
750 } | 927 } |
751 | 928 |
752 void copy_table(char** top, char* end, PackageHashtable* table); | 929 CDS_ONLY(void copy_table(char** top, char* end, PackageHashtable* table);) |
753 }; | 930 }; |
754 | 931 |
755 | 932 #if INCLUDE_CDS |
756 void PackageHashtable::copy_table(char** top, char* end, | 933 void PackageHashtable::copy_table(char** top, char* end, |
757 PackageHashtable* table) { | 934 PackageHashtable* table) { |
758 // Copy (relocate) the table to the shared space. | 935 // Copy (relocate) the table to the shared space. |
759 BasicHashtable<mtClass>::copy_table(top, end); | 936 BasicHashtable<mtClass>::copy_table(top, end); |
760 | 937 |
761 // Calculate the space needed for the package name strings. | 938 // Calculate the space needed for the package name strings. |
762 int i; | 939 int i; |
763 int n = 0; | 940 intptr_t* tableSize = (intptr_t*)(*top); |
764 for (i = 0; i < table_size(); ++i) { | 941 *top += sizeof(intptr_t); // For table size |
765 for (PackageInfo* pp = table->bucket(i); | 942 char* tableStart = *top; |
766 pp != NULL; | |
767 pp = pp->next()) { | |
768 n += (int)(strlen(pp->pkgname()) + 1); | |
769 } | |
770 } | |
771 if (*top + n + sizeof(intptr_t) >= end) { | |
772 report_out_of_shared_space(SharedMiscData); | |
773 } | |
774 | |
775 // Copy the table data (the strings) to the shared space. | |
776 n = align_size_up(n, sizeof(HeapWord)); | |
777 *(intptr_t*)(*top) = n; | |
778 *top += sizeof(intptr_t); | |
779 | 943 |
780 for (i = 0; i < table_size(); ++i) { | 944 for (i = 0; i < table_size(); ++i) { |
781 for (PackageInfo* pp = table->bucket(i); | 945 for (PackageInfo* pp = table->bucket(i); |
782 pp != NULL; | 946 pp != NULL; |
783 pp = pp->next()) { | 947 pp = pp->next()) { |
784 int n1 = (int)(strlen(pp->pkgname()) + 1); | 948 int n1 = (int)(strlen(pp->pkgname()) + 1); |
949 if (*top + n1 >= end) { | |
950 report_out_of_shared_space(SharedMiscData); | |
951 } | |
785 pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1)); | 952 pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1)); |
786 *top += n1; | 953 *top += n1; |
787 } | 954 } |
788 } | 955 } |
789 *top = (char*)align_size_up((intptr_t)*top, sizeof(HeapWord)); | 956 *top = (char*)align_size_up((intptr_t)*top, sizeof(HeapWord)); |
957 if (*top >= end) { | |
958 report_out_of_shared_space(SharedMiscData); | |
959 } | |
960 | |
961 // Write table size | |
962 intptr_t len = *top - (char*)tableStart; | |
963 *tableSize = len; | |
790 } | 964 } |
791 | 965 |
792 | 966 |
793 void ClassLoader::copy_package_info_buckets(char** top, char* end) { | 967 void ClassLoader::copy_package_info_buckets(char** top, char* end) { |
794 _package_hash_table->copy_buckets(top, end); | 968 _package_hash_table->copy_buckets(top, end); |
795 } | 969 } |
796 | 970 |
797 void ClassLoader::copy_package_info_table(char** top, char* end) { | 971 void ClassLoader::copy_package_info_table(char** top, char* end) { |
798 _package_hash_table->copy_table(top, end, _package_hash_table); | 972 _package_hash_table->copy_table(top, end, _package_hash_table); |
799 } | 973 } |
800 | 974 #endif |
801 | 975 |
802 PackageInfo* ClassLoader::lookup_package(const char *pkgname) { | 976 PackageInfo* ClassLoader::lookup_package(const char *pkgname) { |
803 const char *cp = strrchr(pkgname, '/'); | 977 const char *cp = strrchr(pkgname, '/'); |
804 if (cp != NULL) { | 978 if (cp != NULL) { |
805 // Package prefix found | 979 // Package prefix found |
888 } | 1062 } |
889 | 1063 |
890 | 1064 |
891 instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { | 1065 instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { |
892 ResourceMark rm(THREAD); | 1066 ResourceMark rm(THREAD); |
893 EventMark m("loading class %s", h_name->as_C_string()); | 1067 const char* class_name = h_name->as_C_string(); |
1068 EventMark m("loading class %s", class_name); | |
894 ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion); | 1069 ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion); |
895 | 1070 |
896 stringStream st; | 1071 stringStream st; |
897 // st.print() uses too much stack space while handling a StackOverflowError | 1072 // st.print() uses too much stack space while handling a StackOverflowError |
898 // st.print("%s.class", h_name->as_utf8()); | 1073 // st.print("%s.class", h_name->as_utf8()); |
899 st.print_raw(h_name->as_utf8()); | 1074 st.print_raw(h_name->as_utf8()); |
900 st.print_raw(".class"); | 1075 st.print_raw(".class"); |
901 char* name = st.as_string(); | 1076 const char* file_name = st.as_string(); |
1077 ClassLoaderExt::Context context(class_name, file_name, THREAD); | |
902 | 1078 |
903 // Lookup stream for parsing .class file | 1079 // Lookup stream for parsing .class file |
904 ClassFileStream* stream = NULL; | 1080 ClassFileStream* stream = NULL; |
905 int classpath_index = 0; | 1081 int classpath_index = 0; |
1082 ClassPathEntry* e = NULL; | |
1083 instanceKlassHandle h; | |
906 { | 1084 { |
907 PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), | 1085 PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), |
908 ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), | 1086 ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), |
909 PerfClassTraceTime::CLASS_LOAD); | 1087 PerfClassTraceTime::CLASS_LOAD); |
910 ClassPathEntry* e = _first_entry; | 1088 e = _first_entry; |
911 while (e != NULL) { | 1089 while (e != NULL) { |
912 stream = e->open_stream(name, CHECK_NULL); | 1090 stream = e->open_stream(file_name, CHECK_NULL); |
1091 if (!context.check(stream, classpath_index)) { | |
1092 return h; // NULL | |
1093 } | |
913 if (stream != NULL) { | 1094 if (stream != NULL) { |
914 break; | 1095 break; |
915 } | 1096 } |
916 e = e->next(); | 1097 e = e->next(); |
917 ++classpath_index; | 1098 ++classpath_index; |
918 } | 1099 } |
919 } | 1100 } |
920 | 1101 |
921 instanceKlassHandle h; | |
922 if (stream != NULL) { | 1102 if (stream != NULL) { |
923 | |
924 // class file found, parse it | 1103 // class file found, parse it |
925 ClassFileParser parser(stream); | 1104 ClassFileParser parser(stream); |
926 ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); | 1105 ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); |
927 Handle protection_domain; | 1106 Handle protection_domain; |
928 TempNewSymbol parsed_name = NULL; | 1107 TempNewSymbol parsed_name = NULL; |
929 instanceKlassHandle result = parser.parseClassFile(h_name, | 1108 instanceKlassHandle result = parser.parseClassFile(h_name, |
930 loader_data, | 1109 loader_data, |
931 protection_domain, | 1110 protection_domain, |
932 parsed_name, | 1111 parsed_name, |
933 false, | 1112 context.should_verify(classpath_index), |
934 CHECK_(h)); | 1113 THREAD); |
935 | 1114 if (HAS_PENDING_EXCEPTION) { |
936 // add to package table | 1115 ResourceMark rm; |
937 if (add_package(name, classpath_index, THREAD)) { | 1116 if (DumpSharedSpaces) { |
938 h = result; | 1117 tty->print_cr("Preload Error: Failed to load %s", class_name); |
1118 } | |
1119 return h; | |
1120 } | |
1121 h = context.record_result(classpath_index, e, result, THREAD); | |
1122 } else { | |
1123 if (DumpSharedSpaces) { | |
1124 tty->print_cr("Preload Error: Cannot find %s", class_name); | |
939 } | 1125 } |
940 } | 1126 } |
941 | 1127 |
942 return h; | 1128 return h; |
943 } | 1129 } |
1028 } | 1214 } |
1029 } | 1215 } |
1030 | 1216 |
1031 // lookup zip library entry points | 1217 // lookup zip library entry points |
1032 load_zip_library(); | 1218 load_zip_library(); |
1219 #if INCLUDE_CDS | |
1033 // initialize search path | 1220 // initialize search path |
1221 if (DumpSharedSpaces) { | |
1222 _shared_paths_misc_info = SharedClassUtil::allocate_shared_paths_misc_info(); | |
1223 } | |
1224 #endif | |
1034 setup_bootstrap_search_path(); | 1225 setup_bootstrap_search_path(); |
1035 if (LazyBootClassLoader) { | 1226 if (LazyBootClassLoader) { |
1036 // set up meta index which makes boot classpath initialization lazier | 1227 // set up meta index which makes boot classpath initialization lazier |
1037 setup_meta_index(); | 1228 setup_bootstrap_meta_index(); |
1038 } | 1229 } |
1039 } | 1230 } |
1040 | 1231 |
1232 #if INCLUDE_CDS | |
1233 void ClassLoader::initialize_shared_path() { | |
1234 if (DumpSharedSpaces) { | |
1235 ClassLoaderExt::setup_search_paths(); | |
1236 _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check() | |
1237 } | |
1238 } | |
1239 #endif | |
1041 | 1240 |
1042 jlong ClassLoader::classloader_time_ms() { | 1241 jlong ClassLoader::classloader_time_ms() { |
1043 return UsePerfData ? | 1242 return UsePerfData ? |
1044 Management::ticks_to_ms(_perf_accumulated_time->get_value()) : -1; | 1243 Management::ticks_to_ms(_perf_accumulated_time->get_value()) : -1; |
1045 } | 1244 } |