duke@435: /* hseigel@5528: * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_MEMORY_FILEMAP_HPP stefank@2314: #define SHARE_VM_MEMORY_FILEMAP_HPP stefank@2314: coleenp@4037: #include "memory/metaspaceShared.hpp" stefank@5863: #include "memory/metaspace.hpp" stefank@2314: duke@435: // Layout of the file: duke@435: // header: dump of archive instance plus versioning info, datestamp, etc. duke@435: // [magic # = 0xF00BABA2] duke@435: // ... padding to align on page-boundary duke@435: // read-write space from CompactingPermGenGen duke@435: // read-only space from CompactingPermGenGen duke@435: // misc data (block offset table, string table, symbols, dictionary, etc.) duke@435: // tag(666) duke@435: duke@435: static const int JVM_IDENT_MAX = 256; duke@435: coleenp@4037: class Metaspace; duke@435: iklam@7089: class SharedClassPathEntry VALUE_OBJ_CLASS_SPEC { iklam@7089: public: iklam@7089: const char *_name; iklam@7089: time_t _timestamp; // jar timestamp, 0 if is directory iklam@7089: long _filesize; // jar file size, -1 if is directory iklam@7089: bool is_dir() { iklam@7089: return _filesize == -1; iklam@7089: } iklam@7089: }; iklam@7089: zgu@3900: class FileMapInfo : public CHeapObj { duke@435: private: iklam@7089: friend class ManifestStream; duke@435: enum { duke@435: _invalid_version = -1, iklam@7089: _current_version = 2 duke@435: }; duke@435: duke@435: bool _file_open; duke@435: int _fd; jiangli@6868: size_t _file_offset; duke@435: iklam@7089: private: iklam@7089: static SharedClassPathEntry* _classpath_entry_table; iklam@7089: static int _classpath_entry_table_size; iklam@7089: static size_t _classpath_entry_size; iklam@7089: static bool _validating_classpath_entry_table; iklam@7089: duke@435: // FileMapHeader describes the shared space data in the file to be duke@435: // mapped. This structure gets written to a file. It is not a class, so duke@435: // that the compilers don't add any compiler-private data to it. duke@435: iklam@7089: public: iklam@7089: struct FileMapHeaderBase : public CHeapObj { iklam@7089: virtual bool validate() = 0; iklam@7089: virtual void populate(FileMapInfo* info, size_t alignment) = 0; iklam@7089: }; iklam@7089: struct FileMapHeader : FileMapHeaderBase { iklam@7089: // Use data() and data_size() to memcopy to/from the FileMapHeader. We need to iklam@7089: // avoid read/writing the C++ vtable pointer. iklam@7089: static size_t data_size(); iklam@7089: char* data() { iklam@7089: return ((char*)this) + sizeof(FileMapHeaderBase); iklam@7089: } iklam@7089: duke@435: int _magic; // identify file type. jiangli@6868: int _crc; // header crc checksum. duke@435: int _version; // (from enum, above.) duke@435: size_t _alignment; // how shared archive should be aligned hseigel@4397: int _obj_alignment; // value of ObjectAlignmentInBytes duke@435: duke@435: struct space_info { jiangli@6868: int _crc; // crc checksum of the current space jiangli@6868: size_t _file_offset; // sizeof(this) rounded to vm page size duke@435: char* _base; // copy-on-write base address duke@435: size_t _capacity; // for validity checking duke@435: size_t _used; // for setting space top on read duke@435: bool _read_only; // read only space? duke@435: bool _allow_exec; // executable code in space? coleenp@4037: } _space[MetaspaceShared::n_regions]; duke@435: duke@435: // The following fields are all sanity checks for whether this archive duke@435: // will function correctly with this JVM and the bootclasspath it's duke@435: // invoked with. duke@435: char _jvm_ident[JVM_IDENT_MAX]; // identifier for jvm duke@435: iklam@7089: // The _paths_misc_info is a variable-size structure that records "miscellaneous" iklam@7089: // information during dumping. It is generated and validated by the iklam@7089: // SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp and sharedClassUtil.hpp for iklam@7089: // detailed description. iklam@7089: // iklam@7089: // The _paths_misc_info data is stored as a byte array in the archive file header, iklam@7089: // immediately after the _header field. This information is used only when iklam@7089: // checking the validity of the archive and is deallocated after the archive is loaded. iklam@7089: // iklam@7089: // Note that the _paths_misc_info does NOT include information for JAR files iklam@7089: // that existed during dump time. Their information is stored in _classpath_entry_table. iklam@7089: int _paths_misc_info_size; duke@435: iklam@7089: // The following is a table of all the class path entries that were used iklam@7089: // during dumping. At run time, we require these files to exist and have the same iklam@7089: // size/modification time, or else the archive will refuse to load. iklam@7089: // iklam@7089: // All of these entries must be JAR files. The dumping process would fail if a non-empty iklam@7089: // directory was specified in the classpaths. If an empty directory was specified iklam@7089: // it is checked by the _paths_misc_info as described above. iklam@7089: // iklam@7089: // FIXME -- if JAR files in the tail of the list were specified but not used during dumping, iklam@7089: // they should be removed from this table, to save space and to avoid spurious iklam@7089: // loading failures during runtime. iklam@7089: int _classpath_entry_table_size; iklam@7089: size_t _classpath_entry_size; iklam@7089: SharedClassPathEntry* _classpath_entry_table; iklam@7089: iklam@7089: virtual bool validate(); iklam@7089: virtual void populate(FileMapInfo* info, size_t alignment); jiangli@7241: int compute_crc(); iklam@7089: }; iklam@7089: iklam@7089: FileMapHeader * _header; iklam@7089: duke@435: const char* _full_path; iklam@7089: char* _paths_misc_info; duke@435: duke@435: static FileMapInfo* _current_info; duke@435: duke@435: bool init_from_file(int fd); duke@435: void align_file_position(); iklam@7089: bool validate_header_impl(); duke@435: duke@435: public: iklam@7089: FileMapInfo(); iklam@7089: ~FileMapInfo(); duke@435: duke@435: static int current_version() { return _current_version; } jiangli@6868: int compute_header_crc(); jiangli@7241: void set_header_crc(int crc) { _header->_crc = crc; } duke@435: void populate_header(size_t alignment); iklam@7089: bool validate_header(); duke@435: void invalidate(); iklam@7089: int version() { return _header->_version; } iklam@7089: size_t alignment() { return _header->_alignment; } iklam@7089: size_t space_capacity(int i) { return _header->_space[i]._capacity; } iklam@7089: char* region_base(int i) { return _header->_space[i]._base; } iklam@7089: struct FileMapHeader* header() { return _header; } jprovino@4720: jprovino@4720: static FileMapInfo* current_info() { jprovino@4720: CDS_ONLY(return _current_info;) jprovino@4720: NOT_CDS(return NULL;) jprovino@4720: } jprovino@4720: duke@435: static void assert_mark(bool check); duke@435: duke@435: // File manipulation. jprovino@4720: bool initialize() NOT_CDS_RETURN_(false); duke@435: bool open_for_read(); duke@435: void open_for_write(); duke@435: void write_header(); coleenp@4037: void write_space(int i, Metaspace* space, bool read_only); duke@435: void write_region(int region, char* base, size_t size, duke@435: size_t capacity, bool read_only, bool allow_exec); duke@435: void write_bytes(const void* buffer, int count); duke@435: void write_bytes_aligned(const void* buffer, int count); coleenp@4037: char* map_region(int i); duke@435: void unmap_region(int i); jiangli@6868: bool verify_region_checksum(int i); duke@435: void close(); duke@435: bool is_open() { return _file_open; } coleenp@4037: ReservedSpace reserve_shared_memory(); duke@435: duke@435: // JVM/TI RedefineClasses() support: duke@435: // Remap the shared readonly space to shared readwrite, private. duke@435: bool remap_shared_readonly_as_readwrite(); duke@435: duke@435: // Errors. duke@435: static void fail_stop(const char *msg, ...); iklam@7089: static void fail_continue(const char *msg, ...); duke@435: duke@435: // Return true if given address is in the mapped shared space. jprovino@4720: bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false); iklam@5329: void print_shared_spaces() NOT_CDS_RETURN; hseigel@5528: hseigel@5528: static size_t shared_spaces_size() { hseigel@5528: return align_size_up(SharedReadOnlySize + SharedReadWriteSize + hseigel@5528: SharedMiscDataSize + SharedMiscCodeSize, hseigel@5528: os::vm_allocation_granularity()); hseigel@5528: } hseigel@5528: hseigel@5528: // Stop CDS sharing and unmap CDS regions. hseigel@5528: static void stop_sharing_and_unmap(const char* msg); iklam@7089: iklam@7089: static void allocate_classpath_entry_table(); iklam@7089: bool validate_classpath_entry_table(); iklam@7089: iklam@7089: static SharedClassPathEntry* shared_classpath(int index) { iklam@7089: char* p = (char*)_classpath_entry_table; iklam@7089: p += _classpath_entry_size * index; iklam@7089: return (SharedClassPathEntry*)p; iklam@7089: } iklam@7089: static const char* shared_classpath_name(int index) { iklam@7089: return shared_classpath(index)->_name; iklam@7089: } iklam@7089: iklam@7089: static int get_number_of_share_classpaths() { iklam@7089: return _classpath_entry_table_size; iklam@7089: } duke@435: }; stefank@2314: stefank@2314: #endif // SHARE_VM_MEMORY_FILEMAP_HPP