/** * 使用当前JVM的jar包 */ void FileMapInfo::populate_header(size_t alignment) { _header._magic = 0xf00baba2; _header._version = _current_version; _header._alignment = alignment; // The following fields are for sanity checks for whether this archive // will function correctly with this JVM and the bootclasspath it's // invoked with. // JVM version string ... changes on each build. const char *vm_version = VM_Version::internal_vm_info_string(); if (strlen(vm_version) < (JVM_IDENT_MAX-1)) { strcpy(_header._jvm_ident, vm_version); } else { fail_stop("JVM Ident field for shared archive is too long" " - truncated to <%s>", _header._jvm_ident); } // Build checks on classpath and jar files _header._num_jars = 0; ClassPathEntry *cpe = ClassLoader::classpath_entry(0); for ( ; cpe != NULL; cpe = cpe->next()) { if (cpe->is_jar_file()) { //jar包文件 if (_header._num_jars >= JVM_SHARED_JARS_MAX) { fail_stop("Too many jar files to share.", NULL); } // Jar file - record timestamp and file size. struct stat st; const char *path = cpe->name(); if (os::stat(path, &st) != 0) { // If we can't access a jar file in the boot path, then we can't // make assumptions about where classes get loaded from. fail_stop("Unable to open jar file %s.", path); } _header._jar[_header._num_jars]._timestamp = st.st_mtime; _header._jar[_header._num_jars]._filesize = st.st_size; _header._num_jars++; } else { // If directories appear in boot classpath, they must be empty to // avoid having to verify each individual class file. const char* name = ((ClassPathDirEntry*)cpe)->name(); if (!os::dir_is_empty(name)) { fail_stop("Boot classpath directory %s is not empty.", name); } } } }
/** * 检查jar包是否可共享 */ bool FileMapInfo::validate() { if (_header._version != current_version()) { fail_continue("The shared archive file is the wrong version."); return false; } if (_header._magic != (int)0xf00baba2) { fail_continue("The shared archive file has a bad magic number."); return false; } if (strncmp(_header._jvm_ident, VM_Version::internal_vm_info_string(), JVM_IDENT_MAX-1) != 0) { fail_continue("The shared archive file was created by a different" " version or build of HotSpot."); return false; } // Cannot verify interpreter yet, as it can only be created after the GC // heap has been initialized. if (_header._num_jars >= JVM_SHARED_JARS_MAX) { fail_continue("Too many jar files to share."); return false; } // Build checks on classpath and jar files int num_jars_now = 0; ClassPathEntry *cpe = ClassLoader::classpath_entry(0); for ( ; cpe != NULL; cpe = cpe->next()) { if (cpe->is_jar_file()) { //jar包文件 if (num_jars_now < _header._num_jars) { // Jar file - verify timestamp and file size. struct stat st; const char *path = cpe->name(); if (os::stat(path, &st) != 0) { fail_continue("Unable to open jar file %s.", path); return false; } //jar包已被修改,不能共享 if (_header._jar[num_jars_now]._timestamp != st.st_mtime || _header._jar[num_jars_now]._filesize != st.st_size) { fail_continue("A jar file is not the one used while building" " the shared archive file."); return false; } } ++num_jars_now; } else { // If directories appear in boot classpath, they must be empty to // avoid having to verify each individual class file. const char* name = ((ClassPathDirEntry*)cpe)->name(); if (!os::dir_is_empty(name)) { //类路径 fail_continue("Boot classpath directory %s is not empty.", name); return false; } } } if (num_jars_now < _header._num_jars) { fail_continue("The number of jar files in the boot classpath is" " less than the number the shared archive was created with."); return false; } return true; }
void FileMapInfo::allocate_classpath_entry_table() { int bytes = 0; int count = 0; char* strptr = NULL; char* strptr_max = NULL; Thread* THREAD = Thread::current(); ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); size_t entry_size = SharedClassUtil::shared_class_path_entry_size(); for (int pass=0; pass<2; pass++) { ClassPathEntry *cpe = ClassLoader::classpath_entry(0); for (int cur_entry = 0 ; cpe != NULL; cpe = cpe->next(), cur_entry++) { const char *name = cpe->name(); int name_bytes = (int)(strlen(name) + 1); if (pass == 0) { count ++; bytes += (int)entry_size; bytes += name_bytes; if (TraceClassPaths || (TraceClassLoading && Verbose)) { tty->print_cr("[Add main shared path (%s) %s]", (cpe->is_jar_file() ? "jar" : "dir"), name); } } else { SharedClassPathEntry* ent = shared_classpath(cur_entry); if (cpe->is_jar_file()) { struct stat st; if (os::stat(name, &st) != 0) { // The file/dir must exist, or it would not have been added // into ClassLoader::classpath_entry(). // // If we can't access a jar file in the boot path, then we can't // make assumptions about where classes get loaded from. FileMapInfo::fail_stop("Unable to open jar file %s.", name); } EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD); } else { ent->_filesize = -1; if (!os::dir_is_empty(name)) { ClassLoader::exit_with_path_failure("Cannot have non-empty directory in archived classpaths", name); } } ent->_name = strptr; if (strptr + name_bytes <= strptr_max) { strncpy(strptr, name, (size_t)name_bytes); // name_bytes includes trailing 0. strptr += name_bytes; } else { assert(0, "miscalculated buffer size"); } } } if (pass == 0) { EXCEPTION_MARK; // The following call should never throw, but would exit VM on error. Array<u8>* arr = MetadataFactory::new_array<u8>(loader_data, (bytes + 7)/8, THREAD); strptr = (char*)(arr->data()); strptr_max = strptr + bytes; SharedClassPathEntry* table = (SharedClassPathEntry*)strptr; strptr += entry_size * count; _classpath_entry_table_size = count; _classpath_entry_table = table; _classpath_entry_size = entry_size; } } }