/** * 使用当前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); } } } }
void FileMapInfo::unmap_region(int i) { struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i]; size_t used = si->_used; size_t size = align_size_up(used, os::vm_allocation_granularity()); if (!os::unmap_memory(si->_base, size)) { fail_stop("Unable to unmap shared space."); } }
void FileMapInfo::close() { if (_file_open) { if (::close(_fd) < 0) { fail_stop("Unable to close the shared archive file."); } _file_open = false; _fd = -1; } }
void FileMapInfo::write_bytes(const void* buffer, int nbytes) { if (_file_open) { int n = ::write(_fd, buffer, nbytes); if (n != nbytes) { // It is dangerous to leave the corrupted shared archive file around, // close and remove the file. See bug 6372906. close(); remove(_full_path); fail_stop("Unable to write to shared archive file.", NULL); } } _file_offset += nbytes; }
// Unmap mapped regions of shared space. void FileMapInfo::stop_sharing_and_unmap(const char* msg) { FileMapInfo *map_info = FileMapInfo::current_info(); if (map_info) { map_info->fail_continue(msg); for (int i = 0; i < MetaspaceShared::n_regions; i++) { if (map_info->_header->_space[i]._base != NULL) { map_info->unmap_region(i); map_info->_header->_space[i]._base = NULL; } } } else if (DumpSharedSpaces) { fail_stop(msg, NULL); } }
void FileMapInfo::unmap_string_regions() { for (int i = MetaspaceShared::first_string; i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) { struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; size_t used = si->_used; if (used > 0) { size_t size = align_size_up(used, os::vm_allocation_granularity()); char* addr = (char*)((void*)oopDesc::decode_heap_oop_not_null( (narrowOop)si->_addr._offset)); if (!os::unmap_memory(addr, size)) { fail_stop("Unable to unmap shared space."); } } } }
void FileMapInfo::unmap_region(int i) { assert(!MetaspaceShared::is_string_region(i), "sanity"); struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; size_t used = si->_used; size_t size = align_size_up(used, os::vm_allocation_granularity()); if (used == 0) { return; } char* addr = _header->region_addr(i); if (!os::unmap_memory(addr, size)) { fail_stop("Unable to unmap shared space."); } }
void FileMapInfo::align_file_position() { long new_file_offset = align_size_up(_file_offset, os::vm_allocation_granularity()); if (new_file_offset != _file_offset) { _file_offset = new_file_offset; if (_file_open) { // Seek one byte back from the target and write a byte to insure // that the written file is the correct length. _file_offset -= 1; if (lseek(_fd, _file_offset, SEEK_SET) < 0) { fail_stop("Unable to seek.", NULL); } char zero = 0; write_bytes(&zero, 1); } } }
// Unmap mapped regions of shared space. void FileMapInfo::stop_sharing_and_unmap(const char* msg) { FileMapInfo *map_info = FileMapInfo::current_info(); if (map_info) { map_info->fail_continue("%s", msg); for (int i = 0; i < MetaspaceShared::num_non_strings; i++) { char *addr = map_info->_header->region_addr(i); if (addr != NULL && !MetaspaceShared::is_string_region(i)) { map_info->unmap_region(i); map_info->_header->_space[i]._addr._base = NULL; } } map_info->unmap_string_regions(); } else if (DumpSharedSpaces) { fail_stop("%s", msg); } }
void FileMapInfo::open_for_write() { _full_path = Arguments::GetSharedArchivePath(); if (PrintSharedSpaces) { tty->print_cr("Dumping shared data to file: "); tty->print_cr(" %s", _full_path); } // Remove the existing file in case another process has it open. remove(_full_path); int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444); if (fd < 0) { fail_stop("Unable to create shared archive file %s.", _full_path); } _fd = fd; _file_offset = 0; _file_open = true; }
void FileMapInfo::open_for_write() { _full_path = Arguments::GetSharedArchivePath(); if (PrintSharedSpaces) { tty->print_cr("Dumping shared data to file: "); tty->print_cr(" %s", _full_path); } #ifdef _WINDOWS // On Windows, need WRITE permission to remove the file. chmod(_full_path, _S_IREAD | _S_IWRITE); #endif // Use remove() to delete the existing file because, on Unix, this will // allow processes that have it open continued access to the file. remove(_full_path); int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444); if (fd < 0) { fail_stop("Unable to create shared archive file %s.", _full_path); } _fd = fd; _file_offset = 0; _file_open = true; }
void FileMapInfo::assert_mark(bool check) { if (!check) { fail_stop("Mark mismatch while restoring from shared file.", NULL); } }