src/share/vm/classfile/classLoader.cpp

Print this page

        

*** 26,35 **** --- 26,36 ---- #include "classfile/classFileParser.hpp" #include "classfile/classFileStream.hpp" #include "classfile/classLoader.hpp" #include "classfile/classLoaderExt.hpp" #include "classfile/classLoaderData.inline.hpp" + #include "classfile/imageFile.hpp" #include "classfile/javaClasses.hpp" #if INCLUDE_CDS #include "classfile/sharedPathsMiscInfo.hpp" #include "classfile/sharedClassUtil.hpp" #endif
*** 65,91 **** #include "services/threadService.hpp" #include "utilities/events.hpp" #include "utilities/hashtable.hpp" #include "utilities/hashtable.inline.hpp" ! // Entry points in zip.dll for loading zip/jar file entries typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg); typedef void (JNICALL *ZipClose_t)(jzfile *zip); typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen); typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf); typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf); typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n); typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len); static ZipOpen_t ZipOpen = NULL; static ZipClose_t ZipClose = NULL; static FindEntry_t FindEntry = NULL; static ReadEntry_t ReadEntry = NULL; static ReadMappedEntry_t ReadMappedEntry = NULL; static GetNextEntry_t GetNextEntry = NULL; static canonicalize_fn_t CanonicalizeEntry = NULL; static Crc32_t Crc32 = NULL; // Globals PerfCounter* ClassLoader::_perf_accumulated_time = NULL; --- 66,94 ---- #include "services/threadService.hpp" #include "utilities/events.hpp" #include "utilities/hashtable.hpp" #include "utilities/hashtable.inline.hpp" ! // Entry points in zip.dll for loading zip/jar file entries and image file entries typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg); typedef void (JNICALL *ZipClose_t)(jzfile *zip); typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen); typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf); typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf); typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n); + typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg); typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len); static ZipOpen_t ZipOpen = NULL; static ZipClose_t ZipClose = NULL; static FindEntry_t FindEntry = NULL; static ReadEntry_t ReadEntry = NULL; static ReadMappedEntry_t ReadMappedEntry = NULL; static GetNextEntry_t GetNextEntry = NULL; static canonicalize_fn_t CanonicalizeEntry = NULL; + static ZipInflateFully_t ZipInflateFully = NULL; static Crc32_t Crc32 = NULL; // Globals PerfCounter* ClassLoader::_perf_accumulated_time = NULL;
*** 320,329 **** --- 323,334 ---- LazyClassPathEntry::~LazyClassPathEntry() { os::free((void*)_path); } bool LazyClassPathEntry::is_jar_file() { + size_t len = strlen(_path); + if (len < 4 || strcmp(_path + len - 4, ".jar") != 0) return false; return ((_st.st_mode & S_IFREG) == S_IFREG); } ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) { if (_resolved_entry != NULL) {
*** 383,392 **** --- 388,469 ---- *filesize = 0; return NULL; } } + ClassPathImageEntry::ClassPathImageEntry(char* name) : ClassPathEntry(), _image(new ImageFile(name)) { + bool opened = _image->open(); + if (!opened) { + _image = NULL; + } + } + + ClassPathImageEntry::~ClassPathImageEntry() { + if (_image) { + _image->close(); + _image = NULL; + } + } + + const char* ClassPathImageEntry::name() { + return _image ? _image->name() : ""; + } + + ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) { + u1* buffer; + u8 size; + _image->get_resource(name, buffer, size); + + if (buffer) { + if (UsePerfData) { + ClassLoader::perf_sys_classfile_bytes_read()->inc(size); + } + return new ClassFileStream(buffer, (int)size, (char*)name); // Resource allocated + } + + return NULL; + } + + #ifndef PRODUCT + void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) { + tty->print_cr("CompileTheWorld : Compiling all classes in %s", name()); + tty->cr(); + const ImageStrings strings = _image->get_strings(); + // Retrieve each path component string. + u4 count = _image->get_location_count(); + for (u4 i = 0; i < count; i++) { + u1* location_data = _image->get_location_data(i); + + if (location_data) { + ImageLocation location(location_data); + const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings); + const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); + const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings); + assert((strlen(parent) + strlen(base) + strlen(extension)) < JVM_MAXPATHLEN, "path exceeds buffer"); + char path[JVM_MAXPATHLEN]; + strcpy(path, parent); + strcat(path, base); + strcat(path, extension); + ClassLoader::compile_the_world_in(path, loader, CHECK); + } + } + if (HAS_PENDING_EXCEPTION) { + if (PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) { + CLEAR_PENDING_EXCEPTION; + tty->print_cr("\nCompileTheWorld : Ran out of memory\n"); + tty->print_cr("Increase class metadata storage if a limit was set"); + } else { + tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n"); + } + } + } + + bool ClassPathImageEntry::is_jrt() { + return string_ends_with(name(), "bootmodules.jimage"); + } + #endif + static void print_meta_index(LazyClassPathEntry* entry, GrowableArray<char*>& meta_packages) { tty->print("[Meta index for %s=", entry->name()); for (int i = 0; i < meta_packages.length(); i++) { if (i > 0) tty->print(" ");
*** 632,665 **** if (lazy) { return new LazyClassPathEntry(path, st, throw_exception); } ClassPathEntry* new_entry = NULL; if ((st->st_mode & S_IFREG) == S_IFREG) { ! // Regular file, should be a zip file // Canonicalized filename char canonical_path[JVM_MAXPATHLEN]; if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { // This matches the classic VM if (throw_exception) { THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL); } else { return NULL; } } char* error_msg = NULL; jzfile* zip; { // enable call to C land ThreadToNativeFromVM ttn(thread); HandleMark hm(thread); zip = (*ZipOpen)(canonical_path, &error_msg); } if (zip != NULL && error_msg == NULL) { new_entry = new ClassPathZipEntry(zip, path); - if (TraceClassLoading || TraceClassPaths) { - tty->print_cr("[Opened %s]", path); - } } else { ResourceMark rm(thread); char *msg; if (error_msg == NULL) { msg = NEW_RESOURCE_ARRAY(char, strlen(path) + 128); ; --- 709,744 ---- if (lazy) { return new LazyClassPathEntry(path, st, throw_exception); } ClassPathEntry* new_entry = NULL; if ((st->st_mode & S_IFREG) == S_IFREG) { ! // Regular file, should be a zip or image file // Canonicalized filename char canonical_path[JVM_MAXPATHLEN]; if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { // This matches the classic VM if (throw_exception) { THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL); } else { return NULL; } } + // TODO - add proper criteria for selecting image file + ClassPathImageEntry* entry = new ClassPathImageEntry(canonical_path); + if (entry->is_open()) { + new_entry = entry; + } else { char* error_msg = NULL; jzfile* zip; { // enable call to C land ThreadToNativeFromVM ttn(thread); HandleMark hm(thread); zip = (*ZipOpen)(canonical_path, &error_msg); } if (zip != NULL && error_msg == NULL) { new_entry = new ClassPathZipEntry(zip, path); } else { ResourceMark rm(thread); char *msg; if (error_msg == NULL) { msg = NEW_RESOURCE_ARRAY(char, strlen(path) + 128); ;
*** 673,686 **** THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL); } else { return NULL; } } } else { // Directory new_entry = new ClassPathDirEntry(path); ! if (TraceClassLoading || TraceClassPaths) { tty->print_cr("[Path %s]", path); } } return new_entry; } --- 752,769 ---- THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL); } else { return NULL; } } + } + if (TraceClassLoading || TraceClassPaths) { + tty->print_cr("[Opened %s]", path); + } } else { // Directory new_entry = new ClassPathDirEntry(path); ! if (TraceClassLoading) { tty->print_cr("[Path %s]", path); } } return new_entry; }
*** 799,822 **** --- 882,915 ---- ZipClose = CAST_TO_FN_PTR(ZipClose_t, os::dll_lookup(handle, "ZIP_Close")); FindEntry = CAST_TO_FN_PTR(FindEntry_t, os::dll_lookup(handle, "ZIP_FindEntry")); ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry")); ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry")); GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry")); + ZipInflateFully = CAST_TO_FN_PTR(ZipInflateFully_t, os::dll_lookup(handle, "ZIP_InflateFully")); Crc32 = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32")); + // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || GetNextEntry == NULL || Crc32 == NULL) { vm_exit_during_initialization("Corrupted ZIP library", path); } + if (ZipInflateFully == NULL) { + vm_exit_during_initialization("Corrupted ZIP library ZIP_InflateFully missing", path); + } + // Lookup canonicalize entry in libjava.dll void *javalib_handle = os::native_java_library(); CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, os::dll_lookup(javalib_handle, "Canonicalize")); // This lookup only works on 1.3. Do not check for non-null here } + jboolean ClassLoader::decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg) { + return (*ZipInflateFully)(in, inSize, out, outSize, pmsg); + } + int ClassLoader::crc32(int crc, const char* buf, int len) { assert(Crc32 != NULL, "ZIP_CRC32 is not found"); return (*Crc32)(crc, (const jbyte*)buf, len); }
*** 1366,1376 **** tty->print_cr("CompileTheWorld : Skipped classes in %s", _dir); tty->cr(); } ! bool ClassPathDirEntry::is_rt_jar() { return false; } void ClassPathZipEntry::compile_the_world(Handle loader, TRAPS) { real_jzfile* zip = (real_jzfile*) _zip; --- 1459,1469 ---- tty->print_cr("CompileTheWorld : Skipped classes in %s", _dir); tty->cr(); } ! bool ClassPathDirEntry::is_jrt() { return false; } void ClassPathZipEntry::compile_the_world(Handle loader, TRAPS) { real_jzfile* zip = (real_jzfile*) _zip;
*** 1391,1417 **** tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n"); } } } ! bool ClassPathZipEntry::is_rt_jar() { real_jzfile* zip = (real_jzfile*) _zip; int len = (int)strlen(zip->name); // Check whether zip name ends in "rt.jar" // This will match other archives named rt.jar as well, but this is // only used for debugging. ! return (len >= 6) && (strcasecmp(zip->name + len - 6, "rt.jar") == 0); } void LazyClassPathEntry::compile_the_world(Handle loader, TRAPS) { ClassPathEntry* cpe = resolve_entry(THREAD); if (cpe != NULL) { cpe->compile_the_world(loader, CHECK); } } ! bool LazyClassPathEntry::is_rt_jar() { Thread* THREAD = Thread::current(); ClassPathEntry* cpe = resolve_entry(THREAD); return (cpe != NULL) ? cpe->is_jar_file() : false; } --- 1484,1510 ---- tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n"); } } } ! bool ClassPathZipEntry::is_jrt() { real_jzfile* zip = (real_jzfile*) _zip; int len = (int)strlen(zip->name); // Check whether zip name ends in "rt.jar" // This will match other archives named rt.jar as well, but this is // only used for debugging. ! return string_ends_with(zip->name, "rt.jar"); } void LazyClassPathEntry::compile_the_world(Handle loader, TRAPS) { ClassPathEntry* cpe = resolve_entry(THREAD); if (cpe != NULL) { cpe->compile_the_world(loader, CHECK); } } ! bool LazyClassPathEntry::is_jrt() { Thread* THREAD = Thread::current(); ClassPathEntry* cpe = resolve_entry(THREAD); return (cpe != NULL) ? cpe->is_jar_file() : false; }
*** 1426,1436 **** // Iterate over all bootstrap class path entries ClassPathEntry* e = _first_entry; jlong start = os::javaTimeMillis(); while (e != NULL) { // We stop at rt.jar, unless it is the first bootstrap path entry ! if (e->is_rt_jar() && e != _first_entry) break; e->compile_the_world(system_class_loader, CATCH); e = e->next(); } jlong end = os::javaTimeMillis(); tty->print_cr("CompileTheWorld : Done (%d classes, %d methods, " JLONG_FORMAT " ms)", --- 1519,1529 ---- // Iterate over all bootstrap class path entries ClassPathEntry* e = _first_entry; jlong start = os::javaTimeMillis(); while (e != NULL) { // We stop at rt.jar, unless it is the first bootstrap path entry ! if (e->is_jrt() && e != _first_entry) break; e->compile_the_world(system_class_loader, CATCH); e = e->next(); } jlong end = os::javaTimeMillis(); tty->print_cr("CompileTheWorld : Done (%d classes, %d methods, " JLONG_FORMAT " ms)",
*** 1474,1486 **** return CompilationPolicy::can_be_compiled(m, comp_level); } void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { ! int len = (int)strlen(name); ! if (len > 6 && strcmp(".class", name + len - 6) == 0) { // We have a .class file char buffer[2048]; strncpy(buffer, name, len - 6); buffer[len-6] = 0; // If the file has a period after removing .class, it's not really a // valid class file. The class loader will check everything else. --- 1567,1579 ---- return CompilationPolicy::can_be_compiled(m, comp_level); } void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { ! if (string_ends_with(name, ".class")) { // We have a .class file + int len = (int)strlen(name); char buffer[2048]; strncpy(buffer, name, len - 6); buffer[len-6] = 0; // If the file has a period after removing .class, it's not really a // valid class file. The class loader will check everything else.