src/share/vm/classfile/classLoader.cpp

Print this page
rev 6853 : 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

*** 24,42 **** --- 24,48 ---- #include "precompiled.hpp" #include "classfile/classFileParser.hpp" #include "classfile/classFileStream.hpp" #include "classfile/classLoader.hpp" + #include "classfile/classLoaderExt.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/javaClasses.hpp" + #if INCLUDE_CDS + #include "classfile/sharedPathsMiscInfo.hpp" + #include "classfile/sharedClassUtil.hpp" + #endif #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "compiler/compileBroker.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/oopMapCache.hpp" #include "memory/allocation.inline.hpp" + #include "memory/filemap.hpp" #include "memory/generation.hpp" #include "memory/oopFactory.hpp" #include "memory/universe.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceRefKlass.hpp"
*** 112,123 **** --- 118,133 ---- PerfCounter* ClassLoader::_isUnsyncloadClass = NULL; PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL; ClassPathEntry* ClassLoader::_first_entry = NULL; ClassPathEntry* ClassLoader::_last_entry = NULL; + int ClassLoader::_num_entries = 0; PackageHashtable* ClassLoader::_package_hash_table = NULL; + #if INCLUDE_CDS + SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL; + #endif // helper routines bool string_starts_with(const char* str, const char* str_to_find) { size_t str_len = strlen(str); size_t str_to_find_len = strlen(str_to_find); if (str_to_find_len > str_len) {
*** 192,201 **** --- 202,220 ---- return NULL; } // check if file exists struct stat st; if (os::stat(path, &st) == 0) { + #if INCLUDE_CDS + if (DumpSharedSpaces) { + // We have already check in ClassLoader::check_shared_classpath() that the directory is empty, so + // we should never find a file underneath it -- unless user has added a new file while we are running + // the dump, in which case let's quit! + ShouldNotReachHere(); + ClassLoader::exit_with_path_failure("VM internal error. Classes can be loaded only from JAR files during dump time: %s", path); + } + #endif // found file, open it int file_handle = os::open(path, 0, 0); if (file_handle != -1) { // read contents into resource array u1* buffer = NEW_RESOURCE_ARRAY(u1, st.st_size);
*** 226,264 **** (*ZipClose)(_zip); } FREE_C_HEAP_ARRAY(char, _zip_name, mtClass); } ! ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) { // enable call to C land JavaThread* thread = JavaThread::current(); ThreadToNativeFromVM ttn(thread); // check whether zip archive contains name ! jint filesize, name_len; ! jzentry* entry = (*FindEntry)(_zip, name, &filesize, &name_len); if (entry == NULL) return NULL; u1* buffer; char name_buf[128]; char* filename; if (name_len < 128) { filename = name_buf; } else { filename = NEW_RESOURCE_ARRAY(char, name_len + 1); } ! // file found, get pointer to class in mmaped jar file. if (ReadMappedEntry == NULL || !(*ReadMappedEntry)(_zip, entry, &buffer, filename)) { ! // mmaped access not available, perhaps due to compression, // read contents into resource array ! buffer = NEW_RESOURCE_ARRAY(u1, filesize); if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL; } if (UsePerfData) { ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize); } - // return result return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated } // invoke function for each entry in the zip file void ClassPathZipEntry::contents_do(void f(const char* name, void* context), void* context) { --- 245,297 ---- (*ZipClose)(_zip); } FREE_C_HEAP_ARRAY(char, _zip_name, mtClass); } ! u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) { // enable call to C land JavaThread* thread = JavaThread::current(); ThreadToNativeFromVM ttn(thread); // check whether zip archive contains name ! jint name_len; ! jzentry* entry = (*FindEntry)(_zip, name, filesize, &name_len); if (entry == NULL) return NULL; u1* buffer; char name_buf[128]; char* filename; if (name_len < 128) { filename = name_buf; } else { filename = NEW_RESOURCE_ARRAY(char, name_len + 1); } ! // file found, get pointer to the entry in mmapped jar file. if (ReadMappedEntry == NULL || !(*ReadMappedEntry)(_zip, entry, &buffer, filename)) { ! // mmapped access not available, perhaps due to compression, // read contents into resource array ! int size = (*filesize) + ((nul_terminate) ? 1 : 0); ! buffer = NEW_RESOURCE_ARRAY(u1, size); if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL; } + + // return result + if (nul_terminate) { + buffer[*filesize] = 0; + } + return buffer; + } + + ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) { + jint filesize; + u1* buffer = open_entry(name, &filesize, false, CHECK_NULL); + if (buffer == NULL) { + return NULL; + } if (UsePerfData) { ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize); } return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated } // invoke function for each entry in the zip file void ClassPathZipEntry::contents_do(void f(const char* name, void* context), void* context) {
*** 270,285 **** if (ze == NULL) break; (*f)(ze->name, context); } } ! LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st) : ClassPathEntry() { _path = os::strdup_check_oom(path); _st = *st; _meta_index = NULL; _resolved_entry = NULL; _has_error = false; } LazyClassPathEntry::~LazyClassPathEntry() { os::free(_path); } --- 303,319 ---- if (ze == NULL) break; (*f)(ze->name, context); } } ! LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st, bool throw_exception) : ClassPathEntry() { _path = os::strdup_check_oom(path); _st = *st; _meta_index = NULL; _resolved_entry = NULL; _has_error = false; + _throw_exception = throw_exception; } LazyClassPathEntry::~LazyClassPathEntry() { os::free(_path); }
*** 291,301 **** ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) { if (_resolved_entry != NULL) { return (ClassPathEntry*) _resolved_entry; } ClassPathEntry* new_entry = NULL; ! new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, CHECK_NULL); { ThreadCritical tc; if (_resolved_entry == NULL) { _resolved_entry = new_entry; return new_entry; --- 325,339 ---- ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) { if (_resolved_entry != NULL) { return (ClassPathEntry*) _resolved_entry; } ClassPathEntry* new_entry = NULL; ! new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, _throw_exception, CHECK_NULL); ! if (!_throw_exception && new_entry == NULL) { ! assert(!HAS_PENDING_EXCEPTION, "must be"); ! return NULL; ! } { ThreadCritical tc; if (_resolved_entry == NULL) { _resolved_entry = new_entry; return new_entry;
*** 325,353 **** bool LazyClassPathEntry::is_lazy() { return true; } 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(" "); tty->print("%s", meta_packages.at(i)); } tty->print_cr("]"); } ! void ClassLoader::setup_meta_index() { // Set up meta index which allows us to open boot jars lazily if // class data sharing is enabled const char* known_version = "% VERSION 2"; - char* meta_index_path = Arguments::get_meta_index_path(); - char* meta_index_dir = Arguments::get_meta_index_dir(); FILE* file = fopen(meta_index_path, "r"); int line_no = 0; if (file != NULL) { ResourceMark rm; LazyClassPathEntry* cur_entry = NULL; GrowableArray<char*> boot_class_path_packages(10); char package_name[256]; --- 363,455 ---- bool LazyClassPathEntry::is_lazy() { return true; } + u1* LazyClassPathEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) { + if (_has_error) { + return NULL; + } + ClassPathEntry* cpe = resolve_entry(THREAD); + if (cpe == NULL) { + _has_error = true; + return NULL; + } else if (cpe->is_jar_file()) { + return ((ClassPathZipEntry*)cpe)->open_entry(name, filesize, nul_terminate,THREAD); + } else { + ShouldNotReachHere(); + *filesize = 0; + return NULL; + } + } + 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(" "); tty->print("%s", meta_packages.at(i)); } tty->print_cr("]"); } + #if INCLUDE_CDS + void ClassLoader::exit_with_path_failure(const char* error, const char* message) { + assert(DumpSharedSpaces, "only called at dump time"); + tty->print_cr("Hint: enable -XX:+TraceClassPaths to diagnose the failure"); + vm_exit_during_initialization(error, message); + } + #endif + + void ClassLoader::trace_class_path(const char* msg, const char* name) { + if (!TraceClassPaths) { + return; + } ! if (msg) { ! tty->print("%s", msg); ! } ! if (name) { ! if (strlen(name) < 256) { ! tty->print("%s", name); ! } else { ! // For very long paths, we need to print each character separately, ! // as print_cr() has a length limit ! while (name[0] != '\0') { ! tty->print("%c", name[0]); ! name++; ! } ! } ! } ! if (msg && msg[0] == '[') { ! tty->print_cr("]"); ! } else { ! tty->cr(); ! } ! } ! ! void ClassLoader::setup_bootstrap_meta_index() { // Set up meta index which allows us to open boot jars lazily if // class data sharing is enabled + const char* meta_index_path = Arguments::get_meta_index_path(); + const char* meta_index_dir = Arguments::get_meta_index_dir(); + setup_meta_index(meta_index_path, meta_index_dir, 0); + } + + void ClassLoader::setup_meta_index(const char* meta_index_path, const char* meta_index_dir, int start_index) { const char* known_version = "% VERSION 2"; FILE* file = fopen(meta_index_path, "r"); int line_no = 0; + #if INCLUDE_CDS + if (DumpSharedSpaces) { + if (file != NULL) { + _shared_paths_misc_info->add_required_file(meta_index_path); + } else { + _shared_paths_misc_info->add_nonexist_path(meta_index_path); + } + } + #endif if (file != NULL) { ResourceMark rm; LazyClassPathEntry* cur_entry = NULL; GrowableArray<char*> boot_class_path_packages(10); char package_name[256];
*** 378,400 **** case '@': { // Hand off current packages to current lazy entry (if any) if ((cur_entry != NULL) && (boot_class_path_packages.length() > 0)) { ! if (TraceClassLoading && Verbose) { print_meta_index(cur_entry, boot_class_path_packages); } MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), boot_class_path_packages.length()); cur_entry->set_meta_index(index); } cur_entry = NULL; boot_class_path_packages.clear(); // Find lazy entry corresponding to this jar file ! for (ClassPathEntry* entry = _first_entry; entry != NULL; entry = entry->next()) { ! if (entry->is_lazy() && string_starts_with(entry->name(), meta_index_dir) && string_ends_with(entry->name(), &package_name[2])) { cur_entry = (LazyClassPathEntry*) entry; break; } --- 480,504 ---- case '@': { // Hand off current packages to current lazy entry (if any) if ((cur_entry != NULL) && (boot_class_path_packages.length() > 0)) { ! if ((TraceClassLoading || TraceClassPaths) && Verbose) { print_meta_index(cur_entry, boot_class_path_packages); } MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), boot_class_path_packages.length()); cur_entry->set_meta_index(index); } cur_entry = NULL; boot_class_path_packages.clear(); // Find lazy entry corresponding to this jar file ! int count = 0; ! for (ClassPathEntry* entry = _first_entry; entry != NULL; entry = entry->next(), count++) { ! if (count >= start_index && ! entry->is_lazy() && string_starts_with(entry->name(), meta_index_dir) && string_ends_with(entry->name(), &package_name[2])) { cur_entry = (LazyClassPathEntry*) entry; break; }
*** 427,487 **** } } // Hand off current packages to current lazy entry (if any) if ((cur_entry != NULL) && (boot_class_path_packages.length() > 0)) { ! if (TraceClassLoading && Verbose) { print_meta_index(cur_entry, boot_class_path_packages); } MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), boot_class_path_packages.length()); cur_entry->set_meta_index(index); } fclose(file); } } void ClassLoader::setup_bootstrap_search_path() { assert(_first_entry == NULL, "should not setup bootstrap class search path twice"); char* sys_class_path = os::strdup_check_oom(Arguments::get_sysclasspath()); ! if (TraceClassLoading && Verbose) { ! tty->print_cr("[Bootstrap loader class path=%s]", sys_class_path); } ! int len = (int)strlen(sys_class_path); int end = 0; // Iterate over class path entries for (int start = 0; start < len; start = end) { ! while (sys_class_path[end] && sys_class_path[end] != os::path_separator()[0]) { end++; } ! char* path = NEW_C_HEAP_ARRAY(char, end-start+1, mtClass); ! strncpy(path, &sys_class_path[start], end-start); ! path[end-start] = '\0'; update_class_path_entry_list(path, false); ! FREE_C_HEAP_ARRAY(char, path, mtClass); ! while (sys_class_path[end] == os::path_separator()[0]) { end++; } } - os::free(sys_class_path); } ! ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, bool lazy, TRAPS) { JavaThread* thread = JavaThread::current(); if (lazy) { ! return new LazyClassPathEntry(path, st); } 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 THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL); } char* error_msg = NULL; jzfile* zip; { // enable call to C land --- 531,646 ---- } } // Hand off current packages to current lazy entry (if any) if ((cur_entry != NULL) && (boot_class_path_packages.length() > 0)) { ! if ((TraceClassLoading || TraceClassPaths) && Verbose) { print_meta_index(cur_entry, boot_class_path_packages); } MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0), boot_class_path_packages.length()); cur_entry->set_meta_index(index); } fclose(file); } } + #if INCLUDE_CDS + void ClassLoader::check_shared_classpath(const char *path) { + if (strcmp(path, "") == 0) { + exit_with_path_failure("Cannot have empty path in archived classpaths", NULL); + } + + struct stat st; + if (os::stat(path, &st) == 0) { + if ((st.st_mode & S_IFREG) != S_IFREG) { // is directory + if (!os::dir_is_empty(path)) { + tty->print_cr("Error: non-empty directory '%s'", path); + exit_with_path_failure("CDS allows only empty directories in archived classpaths", NULL); + } + } + } + } + #endif + void ClassLoader::setup_bootstrap_search_path() { assert(_first_entry == NULL, "should not setup bootstrap class search path twice"); char* sys_class_path = os::strdup_check_oom(Arguments::get_sysclasspath()); ! if (!PrintSharedArchiveAndExit) { ! trace_class_path("[Bootstrap loader class path=", sys_class_path); } + #if INCLUDE_CDS + if (DumpSharedSpaces) { + _shared_paths_misc_info->add_boot_classpath(Arguments::get_sysclasspath()); + } + #endif + setup_search_path(sys_class_path); + os::free(sys_class_path); + } + + #if INCLUDE_CDS + int ClassLoader::get_shared_paths_misc_info_size() { + return _shared_paths_misc_info->get_used_bytes(); + } + + void* ClassLoader::get_shared_paths_misc_info() { + return _shared_paths_misc_info->buffer(); + } ! bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) { ! SharedPathsMiscInfo* checker = SharedClassUtil::allocate_shared_paths_misc_info((char*)buf, size); ! bool result = checker->check(); ! delete checker; ! return result; ! } ! #endif ! ! void ClassLoader::setup_search_path(char *class_path) { ! int offset = 0; ! int len = (int)strlen(class_path); int end = 0; // Iterate over class path entries for (int start = 0; start < len; start = end) { ! while (class_path[end] && class_path[end] != os::path_separator()[0]) { end++; } ! EXCEPTION_MARK; ! ResourceMark rm(THREAD); ! char* path = NEW_RESOURCE_ARRAY(char, end - start + 1); ! strncpy(path, &class_path[start], end - start); ! path[end - start] = '\0'; update_class_path_entry_list(path, false); ! #if INCLUDE_CDS ! if (DumpSharedSpaces) { ! check_shared_classpath(path); ! } ! #endif ! while (class_path[end] == os::path_separator()[0]) { end++; } } } ! ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, ! bool lazy, bool throw_exception, TRAPS) { JavaThread* thread = JavaThread::current(); 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
*** 489,499 **** HandleMark hm(thread); zip = (*ZipOpen)(canonical_path, &error_msg); } if (zip != NULL && error_msg == NULL) { new_entry = new ClassPathZipEntry(zip, path); ! if (TraceClassLoading) { tty->print_cr("[Opened %s]", path); } } else { ResourceMark rm(thread); char *msg; --- 648,658 ---- 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;
*** 503,518 **** } else { int len = (int)(strlen(path) + strlen(error_msg) + 128); msg = NEW_RESOURCE_ARRAY(char, len); ; jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); } THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL); } } else { // Directory new_entry = new ClassPathDirEntry(path); ! if (TraceClassLoading) { tty->print_cr("[Path %s]", path); } } return new_entry; } --- 662,681 ---- } else { int len = (int)(strlen(path) + strlen(error_msg) + 128); msg = NEW_RESOURCE_ARRAY(char, len); ; jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); } + if (throw_exception) { 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; }
*** 569,595 **** } else { _last_entry->set_next(new_entry); _last_entry = new_entry; } } } ! void ClassLoader::update_class_path_entry_list(char *path, ! bool check_for_duplicates) { struct stat st; if (os::stat(path, &st) == 0) { // File or directory found ClassPathEntry* new_entry = NULL; Thread* THREAD = Thread::current(); ! new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, CHECK); // The kernel VM adds dynamically to the end of the classloader path and // doesn't reorder the bootclasspath which would break java.lang.Package // (see PackageInfo). // Add new entry to linked list if (!check_for_duplicates || !contains_entry(new_entry)) { ! add_to_list(new_entry); } } } void ClassLoader::print_bootclasspath() { ClassPathEntry* e = _first_entry; --- 732,772 ---- } else { _last_entry->set_next(new_entry); _last_entry = new_entry; } } + _num_entries ++; } ! // Returns true IFF the file/dir exists and the entry was successfully created. ! bool ClassLoader::update_class_path_entry_list(char *path, ! bool check_for_duplicates, ! bool throw_exception) { struct stat st; if (os::stat(path, &st) == 0) { // File or directory found ClassPathEntry* new_entry = NULL; Thread* THREAD = Thread::current(); ! new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, throw_exception, CHECK_(false)); ! if (new_entry == NULL) { ! return false; ! } // The kernel VM adds dynamically to the end of the classloader path and // doesn't reorder the bootclasspath which would break java.lang.Package // (see PackageInfo). // Add new entry to linked list if (!check_for_duplicates || !contains_entry(new_entry)) { ! ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry); } + return true; + } else { + #if INCLUDE_CDS + if (DumpSharedSpaces) { + _shared_paths_misc_info->add_nonexist_path(path); + } + return false; + #endif } } void ClassLoader::print_bootclasspath() { ClassPathEntry* e = _first_entry;
*** 737,795 **** } } assert(n == number_of_entries(), "just checking"); } ! void copy_table(char** top, char* end, PackageHashtable* table); }; ! void PackageHashtable::copy_table(char** top, char* end, PackageHashtable* table) { // Copy (relocate) the table to the shared space. BasicHashtable<mtClass>::copy_table(top, end); // Calculate the space needed for the package name strings. int i; ! int n = 0; ! for (i = 0; i < table_size(); ++i) { ! for (PackageInfo* pp = table->bucket(i); ! pp != NULL; ! pp = pp->next()) { ! n += (int)(strlen(pp->pkgname()) + 1); ! } ! } ! if (*top + n + sizeof(intptr_t) >= end) { ! report_out_of_shared_space(SharedMiscData); ! } ! ! // Copy the table data (the strings) to the shared space. ! n = align_size_up(n, sizeof(HeapWord)); ! *(intptr_t*)(*top) = n; ! *top += sizeof(intptr_t); for (i = 0; i < table_size(); ++i) { for (PackageInfo* pp = table->bucket(i); pp != NULL; pp = pp->next()) { int n1 = (int)(strlen(pp->pkgname()) + 1); pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1)); *top += n1; } } *top = (char*)align_size_up((intptr_t)*top, sizeof(HeapWord)); } void ClassLoader::copy_package_info_buckets(char** top, char* end) { _package_hash_table->copy_buckets(top, end); } void ClassLoader::copy_package_info_table(char** top, char* end) { _package_hash_table->copy_table(top, end, _package_hash_table); } ! PackageInfo* ClassLoader::lookup_package(const char *pkgname) { const char *cp = strrchr(pkgname, '/'); if (cp != NULL) { // Package prefix found --- 914,969 ---- } } assert(n == number_of_entries(), "just checking"); } ! CDS_ONLY(void copy_table(char** top, char* end, PackageHashtable* table);) }; ! #if INCLUDE_CDS void PackageHashtable::copy_table(char** top, char* end, PackageHashtable* table) { // Copy (relocate) the table to the shared space. BasicHashtable<mtClass>::copy_table(top, end); // Calculate the space needed for the package name strings. int i; ! intptr_t* tableSize = (intptr_t*)(*top); ! *top += sizeof(intptr_t); // For table size ! char* tableStart = *top; for (i = 0; i < table_size(); ++i) { for (PackageInfo* pp = table->bucket(i); pp != NULL; pp = pp->next()) { int n1 = (int)(strlen(pp->pkgname()) + 1); + if (*top + n1 >= end) { + report_out_of_shared_space(SharedMiscData); + } pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1)); *top += n1; } } *top = (char*)align_size_up((intptr_t)*top, sizeof(HeapWord)); + if (*top >= end) { + report_out_of_shared_space(SharedMiscData); + } + + // Write table size + intptr_t len = *top - (char*)tableStart; + *tableSize = len; } void ClassLoader::copy_package_info_buckets(char** top, char* end) { _package_hash_table->copy_buckets(top, end); } void ClassLoader::copy_package_info_table(char** top, char* end) { _package_hash_table->copy_table(top, end, _package_hash_table); } ! #endif PackageInfo* ClassLoader::lookup_package(const char *pkgname) { const char *cp = strrchr(pkgname, '/'); if (cp != NULL) { // Package prefix found
*** 878,933 **** } instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { ResourceMark rm(THREAD); ! EventMark m("loading class %s", h_name->as_C_string()); ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion); stringStream st; // st.print() uses too much stack space while handling a StackOverflowError // st.print("%s.class", h_name->as_utf8()); st.print_raw(h_name->as_utf8()); st.print_raw(".class"); ! char* name = st.as_string(); // Lookup stream for parsing .class file ClassFileStream* stream = NULL; int classpath_index = 0; { PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), PerfClassTraceTime::CLASS_LOAD); ! ClassPathEntry* e = _first_entry; while (e != NULL) { ! stream = e->open_stream(name, CHECK_NULL); if (stream != NULL) { break; } e = e->next(); ++classpath_index; } } - instanceKlassHandle h; if (stream != NULL) { - // class file found, parse it ClassFileParser parser(stream); ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); Handle protection_domain; TempNewSymbol parsed_name = NULL; instanceKlassHandle result = parser.parseClassFile(h_name, loader_data, protection_domain, parsed_name, ! false, ! CHECK_(h)); ! ! // add to package table ! if (add_package(name, classpath_index, THREAD)) { ! h = result; } } return h; } --- 1052,1119 ---- } instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { ResourceMark rm(THREAD); ! const char* class_name = h_name->as_C_string(); ! EventMark m("loading class %s", class_name); ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion); stringStream st; // st.print() uses too much stack space while handling a StackOverflowError // st.print("%s.class", h_name->as_utf8()); st.print_raw(h_name->as_utf8()); st.print_raw(".class"); ! const char* file_name = st.as_string(); ! ClassLoaderExt::Context context(class_name, file_name, THREAD); // Lookup stream for parsing .class file ClassFileStream* stream = NULL; int classpath_index = 0; + ClassPathEntry* e = NULL; + instanceKlassHandle h; { PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), PerfClassTraceTime::CLASS_LOAD); ! e = _first_entry; while (e != NULL) { ! stream = e->open_stream(file_name, CHECK_NULL); ! if (!context.check(stream, classpath_index)) { ! return h; // NULL ! } if (stream != NULL) { break; } e = e->next(); ++classpath_index; } } if (stream != NULL) { // class file found, parse it ClassFileParser parser(stream); ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); Handle protection_domain; TempNewSymbol parsed_name = NULL; instanceKlassHandle result = parser.parseClassFile(h_name, loader_data, protection_domain, parsed_name, ! context.should_verify(classpath_index), ! THREAD); ! if (HAS_PENDING_EXCEPTION) { ! ResourceMark rm; ! if (DumpSharedSpaces) { ! tty->print_cr("Preload Error: Failed to load %s", class_name); ! } ! return h; ! } ! h = context.record_result(classpath_index, e, result, THREAD); ! } else { ! if (DumpSharedSpaces) { ! tty->print_cr("Preload Error: Cannot find %s", class_name); } } return h; }
*** 1018,1035 **** } } // lookup zip library entry points load_zip_library(); // initialize search path setup_bootstrap_search_path(); if (LazyBootClassLoader) { // set up meta index which makes boot classpath initialization lazier ! setup_meta_index(); } } jlong ClassLoader::classloader_time_ms() { return UsePerfData ? Management::ticks_to_ms(_perf_accumulated_time->get_value()) : -1; } --- 1204,1234 ---- } } // lookup zip library entry points load_zip_library(); + #if INCLUDE_CDS // initialize search path + if (DumpSharedSpaces) { + _shared_paths_misc_info = SharedClassUtil::allocate_shared_paths_misc_info(); + } + #endif setup_bootstrap_search_path(); if (LazyBootClassLoader) { // set up meta index which makes boot classpath initialization lazier ! setup_bootstrap_meta_index(); } } + #if INCLUDE_CDS + void ClassLoader::initialize_shared_path() { + if (DumpSharedSpaces) { + ClassLoaderExt::setup_search_paths(); + _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check() + } + } + #endif jlong ClassLoader::classloader_time_ms() { return UsePerfData ? Management::ticks_to_ms(_perf_accumulated_time->get_value()) : -1; }