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/classLoaderExt.hpp" |
30 #include "classfile/classLoaderData.inline.hpp" |
30 #include "classfile/classLoaderData.inline.hpp" |
|
31 #include "classfile/imageFile.hpp" |
31 #include "classfile/javaClasses.hpp" |
32 #include "classfile/javaClasses.hpp" |
32 #if INCLUDE_CDS |
33 #if INCLUDE_CDS |
33 #include "classfile/sharedPathsMiscInfo.hpp" |
34 #include "classfile/sharedPathsMiscInfo.hpp" |
34 #include "classfile/sharedClassUtil.hpp" |
35 #include "classfile/sharedClassUtil.hpp" |
35 #endif |
36 #endif |
65 #include "services/threadService.hpp" |
66 #include "services/threadService.hpp" |
66 #include "utilities/events.hpp" |
67 #include "utilities/events.hpp" |
67 #include "utilities/hashtable.hpp" |
68 #include "utilities/hashtable.hpp" |
68 #include "utilities/hashtable.inline.hpp" |
69 #include "utilities/hashtable.inline.hpp" |
69 |
70 |
70 // Entry points in zip.dll for loading zip/jar file entries |
71 // Entry points in zip.dll for loading zip/jar file entries and image file entries |
71 |
72 |
72 typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg); |
73 typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg); |
73 typedef void (JNICALL *ZipClose_t)(jzfile *zip); |
74 typedef void (JNICALL *ZipClose_t)(jzfile *zip); |
74 typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen); |
75 typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen); |
75 typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf); |
76 typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf); |
76 typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf); |
77 typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf); |
77 typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n); |
78 typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n); |
|
79 typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg); |
78 typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len); |
80 typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len); |
79 |
81 |
80 static ZipOpen_t ZipOpen = NULL; |
82 static ZipOpen_t ZipOpen = NULL; |
81 static ZipClose_t ZipClose = NULL; |
83 static ZipClose_t ZipClose = NULL; |
82 static FindEntry_t FindEntry = NULL; |
84 static FindEntry_t FindEntry = NULL; |
83 static ReadEntry_t ReadEntry = NULL; |
85 static ReadEntry_t ReadEntry = NULL; |
84 static ReadMappedEntry_t ReadMappedEntry = NULL; |
86 static ReadMappedEntry_t ReadMappedEntry = NULL; |
85 static GetNextEntry_t GetNextEntry = NULL; |
87 static GetNextEntry_t GetNextEntry = NULL; |
86 static canonicalize_fn_t CanonicalizeEntry = NULL; |
88 static canonicalize_fn_t CanonicalizeEntry = NULL; |
|
89 static ZipInflateFully_t ZipInflateFully = NULL; |
87 static Crc32_t Crc32 = NULL; |
90 static Crc32_t Crc32 = NULL; |
88 |
91 |
89 // Globals |
92 // Globals |
90 |
93 |
91 PerfCounter* ClassLoader::_perf_accumulated_time = NULL; |
94 PerfCounter* ClassLoader::_perf_accumulated_time = NULL; |
320 LazyClassPathEntry::~LazyClassPathEntry() { |
323 LazyClassPathEntry::~LazyClassPathEntry() { |
321 os::free((void*)_path); |
324 os::free((void*)_path); |
322 } |
325 } |
323 |
326 |
324 bool LazyClassPathEntry::is_jar_file() { |
327 bool LazyClassPathEntry::is_jar_file() { |
|
328 size_t len = strlen(_path); |
|
329 if (len < 4 || strcmp(_path + len - 4, ".jar") != 0) return false; |
325 return ((_st.st_mode & S_IFREG) == S_IFREG); |
330 return ((_st.st_mode & S_IFREG) == S_IFREG); |
326 } |
331 } |
327 |
332 |
328 ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) { |
333 ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) { |
329 if (_resolved_entry != NULL) { |
334 if (_resolved_entry != NULL) { |
382 ShouldNotReachHere(); |
387 ShouldNotReachHere(); |
383 *filesize = 0; |
388 *filesize = 0; |
384 return NULL; |
389 return NULL; |
385 } |
390 } |
386 } |
391 } |
|
392 |
|
393 ClassPathImageEntry::ClassPathImageEntry(char* name) : ClassPathEntry(), _image(new ImageFile(name)) { |
|
394 bool opened = _image->open(); |
|
395 if (!opened) { |
|
396 _image = NULL; |
|
397 } |
|
398 } |
|
399 |
|
400 ClassPathImageEntry::~ClassPathImageEntry() { |
|
401 if (_image) { |
|
402 _image->close(); |
|
403 _image = NULL; |
|
404 } |
|
405 } |
|
406 |
|
407 const char* ClassPathImageEntry::name() { |
|
408 return _image ? _image->name() : ""; |
|
409 } |
|
410 |
|
411 ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) { |
|
412 u1* buffer; |
|
413 u8 size; |
|
414 _image->get_resource(name, buffer, size); |
|
415 |
|
416 if (buffer) { |
|
417 if (UsePerfData) { |
|
418 ClassLoader::perf_sys_classfile_bytes_read()->inc(size); |
|
419 } |
|
420 return new ClassFileStream(buffer, (int)size, (char*)name); // Resource allocated |
|
421 } |
|
422 |
|
423 return NULL; |
|
424 } |
|
425 |
|
426 #ifndef PRODUCT |
|
427 void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) { |
|
428 tty->print_cr("CompileTheWorld : Compiling all classes in %s", name()); |
|
429 tty->cr(); |
|
430 const ImageStrings strings = _image->get_strings(); |
|
431 // Retrieve each path component string. |
|
432 u4 count = _image->get_location_count(); |
|
433 for (u4 i = 0; i < count; i++) { |
|
434 u1* location_data = _image->get_location_data(i); |
|
435 |
|
436 if (location_data) { |
|
437 ImageLocation location(location_data); |
|
438 const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings); |
|
439 const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); |
|
440 const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings); |
|
441 assert((strlen(parent) + strlen(base) + strlen(extension)) < JVM_MAXPATHLEN, "path exceeds buffer"); |
|
442 char path[JVM_MAXPATHLEN]; |
|
443 strcpy(path, parent); |
|
444 strcat(path, base); |
|
445 strcat(path, extension); |
|
446 ClassLoader::compile_the_world_in(path, loader, CHECK); |
|
447 } |
|
448 } |
|
449 if (HAS_PENDING_EXCEPTION) { |
|
450 if (PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) { |
|
451 CLEAR_PENDING_EXCEPTION; |
|
452 tty->print_cr("\nCompileTheWorld : Ran out of memory\n"); |
|
453 tty->print_cr("Increase class metadata storage if a limit was set"); |
|
454 } else { |
|
455 tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n"); |
|
456 } |
|
457 } |
|
458 } |
|
459 |
|
460 bool ClassPathImageEntry::is_jrt() { |
|
461 return string_ends_with(name(), "bootmodules.jimage"); |
|
462 } |
|
463 #endif |
387 |
464 |
388 static void print_meta_index(LazyClassPathEntry* entry, |
465 static void print_meta_index(LazyClassPathEntry* entry, |
389 GrowableArray<char*>& meta_packages) { |
466 GrowableArray<char*>& meta_packages) { |
390 tty->print("[Meta index for %s=", entry->name()); |
467 tty->print("[Meta index for %s=", entry->name()); |
391 for (int i = 0; i < meta_packages.length(); i++) { |
468 for (int i = 0; i < meta_packages.length(); i++) { |
632 if (lazy) { |
709 if (lazy) { |
633 return new LazyClassPathEntry(path, st, throw_exception); |
710 return new LazyClassPathEntry(path, st, throw_exception); |
634 } |
711 } |
635 ClassPathEntry* new_entry = NULL; |
712 ClassPathEntry* new_entry = NULL; |
636 if ((st->st_mode & S_IFREG) == S_IFREG) { |
713 if ((st->st_mode & S_IFREG) == S_IFREG) { |
637 // Regular file, should be a zip file |
714 // Regular file, should be a zip or image file |
638 // Canonicalized filename |
715 // Canonicalized filename |
639 char canonical_path[JVM_MAXPATHLEN]; |
716 char canonical_path[JVM_MAXPATHLEN]; |
640 if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { |
717 if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { |
641 // This matches the classic VM |
718 // This matches the classic VM |
642 if (throw_exception) { |
719 if (throw_exception) { |
643 THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL); |
720 THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL); |
644 } else { |
721 } else { |
645 return NULL; |
722 return NULL; |
646 } |
723 } |
647 } |
724 } |
|
725 // TODO - add proper criteria for selecting image file |
|
726 ClassPathImageEntry* entry = new ClassPathImageEntry(canonical_path); |
|
727 if (entry->is_open()) { |
|
728 new_entry = entry; |
|
729 } else { |
648 char* error_msg = NULL; |
730 char* error_msg = NULL; |
649 jzfile* zip; |
731 jzfile* zip; |
650 { |
732 { |
651 // enable call to C land |
733 // enable call to C land |
652 ThreadToNativeFromVM ttn(thread); |
734 ThreadToNativeFromVM ttn(thread); |
653 HandleMark hm(thread); |
735 HandleMark hm(thread); |
654 zip = (*ZipOpen)(canonical_path, &error_msg); |
736 zip = (*ZipOpen)(canonical_path, &error_msg); |
655 } |
737 } |
656 if (zip != NULL && error_msg == NULL) { |
738 if (zip != NULL && error_msg == NULL) { |
657 new_entry = new ClassPathZipEntry(zip, path); |
739 new_entry = new ClassPathZipEntry(zip, path); |
658 if (TraceClassLoading || TraceClassPaths) { |
|
659 tty->print_cr("[Opened %s]", path); |
|
660 } |
|
661 } else { |
740 } else { |
662 ResourceMark rm(thread); |
741 ResourceMark rm(thread); |
663 char *msg; |
742 char *msg; |
664 if (error_msg == NULL) { |
743 if (error_msg == NULL) { |
665 msg = NEW_RESOURCE_ARRAY(char, strlen(path) + 128); ; |
744 msg = NEW_RESOURCE_ARRAY(char, strlen(path) + 128); ; |
799 ZipClose = CAST_TO_FN_PTR(ZipClose_t, os::dll_lookup(handle, "ZIP_Close")); |
882 ZipClose = CAST_TO_FN_PTR(ZipClose_t, os::dll_lookup(handle, "ZIP_Close")); |
800 FindEntry = CAST_TO_FN_PTR(FindEntry_t, os::dll_lookup(handle, "ZIP_FindEntry")); |
883 FindEntry = CAST_TO_FN_PTR(FindEntry_t, os::dll_lookup(handle, "ZIP_FindEntry")); |
801 ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry")); |
884 ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry")); |
802 ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry")); |
885 ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry")); |
803 GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry")); |
886 GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry")); |
|
887 ZipInflateFully = CAST_TO_FN_PTR(ZipInflateFully_t, os::dll_lookup(handle, "ZIP_InflateFully")); |
804 Crc32 = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32")); |
888 Crc32 = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32")); |
805 |
889 |
806 // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL |
890 // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL |
807 if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || |
891 if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || |
808 GetNextEntry == NULL || Crc32 == NULL) { |
892 GetNextEntry == NULL || Crc32 == NULL) { |
809 vm_exit_during_initialization("Corrupted ZIP library", path); |
893 vm_exit_during_initialization("Corrupted ZIP library", path); |
810 } |
894 } |
811 |
895 |
|
896 if (ZipInflateFully == NULL) { |
|
897 vm_exit_during_initialization("Corrupted ZIP library ZIP_InflateFully missing", path); |
|
898 } |
|
899 |
812 // Lookup canonicalize entry in libjava.dll |
900 // Lookup canonicalize entry in libjava.dll |
813 void *javalib_handle = os::native_java_library(); |
901 void *javalib_handle = os::native_java_library(); |
814 CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, os::dll_lookup(javalib_handle, "Canonicalize")); |
902 CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, os::dll_lookup(javalib_handle, "Canonicalize")); |
815 // This lookup only works on 1.3. Do not check for non-null here |
903 // This lookup only works on 1.3. Do not check for non-null here |
|
904 } |
|
905 |
|
906 jboolean ClassLoader::decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg) { |
|
907 return (*ZipInflateFully)(in, inSize, out, outSize, pmsg); |
816 } |
908 } |
817 |
909 |
818 int ClassLoader::crc32(int crc, const char* buf, int len) { |
910 int ClassLoader::crc32(int crc, const char* buf, int len) { |
819 assert(Crc32 != NULL, "ZIP_CRC32 is not found"); |
911 assert(Crc32 != NULL, "ZIP_CRC32 is not found"); |
820 return (*Crc32)(crc, (const jbyte*)buf, len); |
912 return (*Crc32)(crc, (const jbyte*)buf, len); |
1391 tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n"); |
1482 tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n"); |
1392 } |
1483 } |
1393 } |
1484 } |
1394 } |
1485 } |
1395 |
1486 |
1396 bool ClassPathZipEntry::is_rt_jar() { |
1487 bool ClassPathZipEntry::is_jrt() { |
1397 real_jzfile* zip = (real_jzfile*) _zip; |
1488 real_jzfile* zip = (real_jzfile*) _zip; |
1398 int len = (int)strlen(zip->name); |
1489 int len = (int)strlen(zip->name); |
1399 // Check whether zip name ends in "rt.jar" |
1490 // Check whether zip name ends in "rt.jar" |
1400 // This will match other archives named rt.jar as well, but this is |
1491 // This will match other archives named rt.jar as well, but this is |
1401 // only used for debugging. |
1492 // only used for debugging. |
1402 return (len >= 6) && (strcasecmp(zip->name + len - 6, "rt.jar") == 0); |
1493 return string_ends_with(zip->name, "rt.jar"); |
1403 } |
1494 } |
1404 |
1495 |
1405 void LazyClassPathEntry::compile_the_world(Handle loader, TRAPS) { |
1496 void LazyClassPathEntry::compile_the_world(Handle loader, TRAPS) { |
1406 ClassPathEntry* cpe = resolve_entry(THREAD); |
1497 ClassPathEntry* cpe = resolve_entry(THREAD); |
1407 if (cpe != NULL) { |
1498 if (cpe != NULL) { |
1408 cpe->compile_the_world(loader, CHECK); |
1499 cpe->compile_the_world(loader, CHECK); |
1409 } |
1500 } |
1410 } |
1501 } |
1411 |
1502 |
1412 bool LazyClassPathEntry::is_rt_jar() { |
1503 bool LazyClassPathEntry::is_jrt() { |
1413 Thread* THREAD = Thread::current(); |
1504 Thread* THREAD = Thread::current(); |
1414 ClassPathEntry* cpe = resolve_entry(THREAD); |
1505 ClassPathEntry* cpe = resolve_entry(THREAD); |
1415 return (cpe != NULL) ? cpe->is_jar_file() : false; |
1506 return (cpe != NULL) ? cpe->is_jar_file() : false; |
1416 } |
1507 } |
1417 |
1508 |
1426 // Iterate over all bootstrap class path entries |
1517 // Iterate over all bootstrap class path entries |
1427 ClassPathEntry* e = _first_entry; |
1518 ClassPathEntry* e = _first_entry; |
1428 jlong start = os::javaTimeMillis(); |
1519 jlong start = os::javaTimeMillis(); |
1429 while (e != NULL) { |
1520 while (e != NULL) { |
1430 // We stop at rt.jar, unless it is the first bootstrap path entry |
1521 // We stop at rt.jar, unless it is the first bootstrap path entry |
1431 if (e->is_rt_jar() && e != _first_entry) break; |
1522 if (e->is_jrt() && e != _first_entry) break; |
1432 e->compile_the_world(system_class_loader, CATCH); |
1523 e->compile_the_world(system_class_loader, CATCH); |
1433 e = e->next(); |
1524 e = e->next(); |
1434 } |
1525 } |
1435 jlong end = os::javaTimeMillis(); |
1526 jlong end = os::javaTimeMillis(); |
1436 tty->print_cr("CompileTheWorld : Done (%d classes, %d methods, " JLONG_FORMAT " ms)", |
1527 tty->print_cr("CompileTheWorld : Done (%d classes, %d methods, " JLONG_FORMAT " ms)", |
1474 |
1565 |
1475 return CompilationPolicy::can_be_compiled(m, comp_level); |
1566 return CompilationPolicy::can_be_compiled(m, comp_level); |
1476 } |
1567 } |
1477 |
1568 |
1478 void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { |
1569 void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { |
1479 int len = (int)strlen(name); |
1570 if (string_ends_with(name, ".class")) { |
1480 if (len > 6 && strcmp(".class", name + len - 6) == 0) { |
|
1481 // We have a .class file |
1571 // We have a .class file |
|
1572 int len = (int)strlen(name); |
1482 char buffer[2048]; |
1573 char buffer[2048]; |
1483 strncpy(buffer, name, len - 6); |
1574 strncpy(buffer, name, len - 6); |
1484 buffer[len-6] = 0; |
1575 buffer[len-6] = 0; |
1485 // If the file has a period after removing .class, it's not really a |
1576 // If the file has a period after removing .class, it's not really a |
1486 // valid class file. The class loader will check everything else. |
1577 // valid class file. The class loader will check everything else. |