8209657: Refactor filemap.hpp to simplify integration with Serviceability Agent
Added src/hotspot/share/include/cds.h Reviewed-by: ccheung, sspitsyn, jgeorge
This commit is contained in:
parent
bd0f1453dc
commit
73951ab5d9
src
hotspot/share
jdk.hotspot.agent
linux/native/libsaproc
macosx/native/libsaproc
share/classes/sun/jvm/hotspot/memory
solaris/native/libsaproc
test/hotspot/jtreg/runtime/appcds
63
src/hotspot/share/include/cds.h
Normal file
63
src/hotspot/share/include/cds.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_INCLUDE_CDS_H
|
||||
#define SHARE_INCLUDE_CDS_H
|
||||
|
||||
// This file declares the CDS data structures that are used by the HotSpot Serviceability Agent
|
||||
// (see C sources inside src/jdk.hotspot.agent).
|
||||
//
|
||||
// We should use only standard C types. Do not use custom types such as bool, intx,
|
||||
// etc, to avoid introducing unnecessary dependencies to other HotSpot type declarations.
|
||||
//
|
||||
// Also, this is a C header file. Do not use C++ here.
|
||||
|
||||
#define NUM_CDS_REGIONS 9
|
||||
#define CDS_ARCHIVE_MAGIC 0xf00baba2
|
||||
#define CURRENT_CDS_ARCHIVE_VERSION 4
|
||||
#define INVALID_CDS_ARCHIVE_VERSION -1
|
||||
|
||||
struct CDSFileMapRegion {
|
||||
int _crc; // crc checksum of the current space
|
||||
size_t _file_offset; // sizeof(this) rounded to vm page size
|
||||
union {
|
||||
char* _base; // copy-on-write base address
|
||||
size_t _offset; // offset from the compressed oop encoding base, only used
|
||||
// by archive heap space
|
||||
} _addr;
|
||||
size_t _used; // for setting space top on read
|
||||
int _read_only; // read only space?
|
||||
int _allow_exec; // executable code in space?
|
||||
};
|
||||
|
||||
struct CDSFileMapHeaderBase {
|
||||
unsigned int _magic; // identify file type
|
||||
int _crc; // header crc checksum
|
||||
int _version; // must be CURRENT_CDS_ARCHIVE_VERSION
|
||||
struct CDSFileMapRegion _space[NUM_CDS_REGIONS];
|
||||
};
|
||||
|
||||
typedef struct CDSFileMapHeaderBase CDSFileMapHeaderBase;
|
||||
|
||||
#endif // SHARE_INCLUDE_CDS_H
|
@ -159,8 +159,8 @@ FileMapInfo::FileMapInfo() {
|
||||
memset((void*)this, 0, sizeof(FileMapInfo));
|
||||
_file_offset = 0;
|
||||
_file_open = false;
|
||||
_header = new FileMapHeader();
|
||||
_header->_version = _invalid_version;
|
||||
_header = (FileMapHeader*)os::malloc(sizeof(FileMapHeader), mtInternal);
|
||||
_header->_version = INVALID_CDS_ARCHIVE_VERSION;
|
||||
_header->_has_platform_or_app_classes = true;
|
||||
}
|
||||
|
||||
@ -173,9 +173,9 @@ void FileMapInfo::populate_header(size_t alignment) {
|
||||
_header->populate(this, alignment);
|
||||
}
|
||||
|
||||
void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
|
||||
_magic = 0xf00baba2;
|
||||
_version = _current_version;
|
||||
void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
|
||||
_magic = CDS_ARCHIVE_MAGIC;
|
||||
_version = CURRENT_CDS_ARCHIVE_VERSION;
|
||||
_alignment = alignment;
|
||||
_obj_alignment = ObjectAlignmentInBytes;
|
||||
_compact_strings = CompactStrings;
|
||||
@ -493,14 +493,13 @@ bool FileMapInfo::validate_shared_path_table() {
|
||||
// Read the FileMapInfo information from the file.
|
||||
|
||||
bool FileMapInfo::init_from_file(int fd) {
|
||||
size_t sz = _header->data_size();
|
||||
char* addr = _header->data();
|
||||
size_t n = os::read(fd, addr, (unsigned int)sz);
|
||||
size_t sz = sizeof(FileMapHeader);
|
||||
size_t n = os::read(fd, _header, (unsigned int)sz);
|
||||
if (n != sz) {
|
||||
fail_continue("Unable to read the file header.");
|
||||
return false;
|
||||
}
|
||||
if (_header->_version != current_version()) {
|
||||
if (_header->_version != CURRENT_CDS_ARCHIVE_VERSION) {
|
||||
fail_continue("The shared archive file has the wrong version.");
|
||||
return false;
|
||||
}
|
||||
@ -521,8 +520,7 @@ bool FileMapInfo::init_from_file(int fd) {
|
||||
}
|
||||
|
||||
size_t len = lseek(fd, 0, SEEK_END);
|
||||
struct FileMapInfo::FileMapHeader::space_info* si =
|
||||
&_header->_space[MetaspaceShared::last_valid_region];
|
||||
CDSFileMapRegion* si = space_at(MetaspaceShared::last_valid_region);
|
||||
// The last space might be empty
|
||||
if (si->_file_offset > len || len - si->_file_offset < si->_used) {
|
||||
fail_continue("The shared archive file has been truncated.");
|
||||
@ -591,10 +589,8 @@ void FileMapInfo::write_header() {
|
||||
_header->_paths_misc_info_size = info_size;
|
||||
|
||||
align_file_position();
|
||||
size_t sz = _header->data_size();
|
||||
char* addr = _header->data();
|
||||
write_bytes(addr, (int)sz); // skip the C++ vtable
|
||||
write_bytes(ClassLoader::get_shared_paths_misc_info(), info_size);
|
||||
write_bytes(_header, sizeof(FileMapHeader));
|
||||
write_bytes(ClassLoader::get_shared_paths_misc_info(), (size_t)info_size);
|
||||
align_file_position();
|
||||
}
|
||||
|
||||
@ -603,7 +599,7 @@ void FileMapInfo::write_header() {
|
||||
|
||||
void FileMapInfo::write_region(int region, char* base, size_t size,
|
||||
bool read_only, bool allow_exec) {
|
||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[region];
|
||||
CDSFileMapRegion* si = space_at(region);
|
||||
|
||||
if (_file_open) {
|
||||
guarantee(si->_file_offset == _file_offset, "file offset mismatch.");
|
||||
@ -628,7 +624,7 @@ void FileMapInfo::write_region(int region, char* base, size_t size,
|
||||
si->_allow_exec = allow_exec;
|
||||
si->_crc = ClassLoader::crc32(0, base, (jint)size);
|
||||
if (base != NULL) {
|
||||
write_bytes_aligned(base, (int)size);
|
||||
write_bytes_aligned(base, size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -694,9 +690,9 @@ size_t FileMapInfo::write_archive_heap_regions(GrowableArray<MemRegion> *heap_me
|
||||
|
||||
// Dump bytes to file -- at the current file position.
|
||||
|
||||
void FileMapInfo::write_bytes(const void* buffer, int nbytes) {
|
||||
void FileMapInfo::write_bytes(const void* buffer, size_t nbytes) {
|
||||
if (_file_open) {
|
||||
int n = ::write(_fd, buffer, nbytes);
|
||||
size_t n = os::write(_fd, buffer, (unsigned int)nbytes);
|
||||
if (n != nbytes) {
|
||||
// It is dangerous to leave the corrupted shared archive file around,
|
||||
// close and remove the file. See bug 6372906.
|
||||
@ -732,7 +728,7 @@ void FileMapInfo::align_file_position() {
|
||||
|
||||
// Dump bytes to file -- at the current file position.
|
||||
|
||||
void FileMapInfo::write_bytes_aligned(const void* buffer, int nbytes) {
|
||||
void FileMapInfo::write_bytes_aligned(const void* buffer, size_t nbytes) {
|
||||
align_file_position();
|
||||
write_bytes(buffer, nbytes);
|
||||
align_file_position();
|
||||
@ -756,7 +752,7 @@ void FileMapInfo::close() {
|
||||
// Remap the shared readonly space to shared readwrite, private.
|
||||
bool FileMapInfo::remap_shared_readonly_as_readwrite() {
|
||||
int idx = MetaspaceShared::ro;
|
||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[idx];
|
||||
CDSFileMapRegion* si = space_at(idx);
|
||||
if (!si->_read_only) {
|
||||
// the space is already readwrite so we are done
|
||||
return true;
|
||||
@ -808,7 +804,7 @@ static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly",
|
||||
|
||||
char* FileMapInfo::map_region(int i, char** top_ret) {
|
||||
assert(!MetaspaceShared::is_heap_region(i), "sanity");
|
||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
|
||||
CDSFileMapRegion* si = space_at(i);
|
||||
size_t used = si->_used;
|
||||
size_t alignment = os::vm_allocation_granularity();
|
||||
size_t size = align_up(used, alignment);
|
||||
@ -875,7 +871,7 @@ void FileMapInfo::map_heap_regions() {
|
||||
narrow_oop_shift() != Universe::narrow_oop_shift() ||
|
||||
narrow_klass_base() != Universe::narrow_klass_base() ||
|
||||
narrow_klass_shift() != Universe::narrow_klass_shift()) {
|
||||
if (log_is_enabled(Info, cds) && _header->_space[MetaspaceShared::first_string]._used > 0) {
|
||||
if (log_is_enabled(Info, cds) && space_at(MetaspaceShared::first_string)->_used > 0) {
|
||||
log_info(cds)("Cached heap data from the CDS archive is being ignored. "
|
||||
"The current CompressedOops/CompressedClassPointers encoding differs from "
|
||||
"that archived due to heap size change. The archive was dumped using max heap "
|
||||
@ -906,7 +902,7 @@ void FileMapInfo::map_heap_regions() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (log_is_enabled(Info, cds) && _header->_space[MetaspaceShared::first_string]._used > 0) {
|
||||
if (log_is_enabled(Info, cds) && space_at(MetaspaceShared::first_string)->_used > 0) {
|
||||
log_info(cds)("Cached heap data from the CDS archive is being ignored. UseG1GC, "
|
||||
"UseCompressedOops and UseCompressedClassPointers are required.");
|
||||
}
|
||||
@ -924,12 +920,12 @@ void FileMapInfo::map_heap_regions() {
|
||||
bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first,
|
||||
int max, int* num, bool is_open_archive) {
|
||||
MemRegion * regions = new MemRegion[max];
|
||||
struct FileMapInfo::FileMapHeader::space_info* si;
|
||||
CDSFileMapRegion* si;
|
||||
int region_num = 0;
|
||||
|
||||
for (int i = first;
|
||||
i < first + max; i++) {
|
||||
si = &_header->_space[i];
|
||||
si = space_at(i);
|
||||
size_t used = si->_used;
|
||||
if (used > 0) {
|
||||
size_t size = used;
|
||||
@ -963,7 +959,7 @@ bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first,
|
||||
// for mapped regions as they are part of the reserved java heap, which is
|
||||
// already recorded.
|
||||
for (int i = 0; i < region_num; i++) {
|
||||
si = &_header->_space[first + i];
|
||||
si = space_at(first + i);
|
||||
char* addr = (char*)regions[i].start();
|
||||
char* base = os::map_memory(_fd, _full_path, si->_file_offset,
|
||||
addr, regions[i].byte_size(), si->_read_only,
|
||||
@ -1029,7 +1025,7 @@ bool FileMapInfo::verify_region_checksum(int i) {
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t sz = _header->_space[i]._used;
|
||||
size_t sz = space_at(i)->_used;
|
||||
|
||||
if (sz == 0) {
|
||||
return true; // no data
|
||||
@ -1042,7 +1038,7 @@ bool FileMapInfo::verify_region_checksum(int i) {
|
||||
}
|
||||
const char* buf = _header->region_addr(i);
|
||||
int crc = ClassLoader::crc32(0, buf, (jint)sz);
|
||||
if (crc != _header->_space[i]._crc) {
|
||||
if (crc != space_at(i)->_crc) {
|
||||
fail_continue("Checksum verification failed.");
|
||||
return false;
|
||||
}
|
||||
@ -1053,7 +1049,7 @@ bool FileMapInfo::verify_region_checksum(int i) {
|
||||
|
||||
void FileMapInfo::unmap_region(int i) {
|
||||
assert(!MetaspaceShared::is_heap_region(i), "sanity");
|
||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
|
||||
CDSFileMapRegion* si = space_at(i);
|
||||
size_t used = si->_used;
|
||||
size_t size = align_up(used, os::vm_allocation_granularity());
|
||||
|
||||
@ -1111,7 +1107,7 @@ bool FileMapInfo::initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
char* FileMapInfo::FileMapHeader::region_addr(int idx) {
|
||||
char* FileMapHeader::region_addr(int idx) {
|
||||
if (MetaspaceShared::is_heap_region(idx)) {
|
||||
return _space[idx]._used > 0 ?
|
||||
(char*)((void*)CompressedOops::decode_not_null((narrowOop)_space[idx]._addr._offset)) : NULL;
|
||||
@ -1120,19 +1116,19 @@ char* FileMapInfo::FileMapHeader::region_addr(int idx) {
|
||||
}
|
||||
}
|
||||
|
||||
int FileMapInfo::FileMapHeader::compute_crc() {
|
||||
char* header = data();
|
||||
int FileMapHeader::compute_crc() {
|
||||
char* start = (char*)this;
|
||||
// start computing from the field after _crc
|
||||
char* buf = (char*)&_crc + sizeof(int);
|
||||
size_t sz = data_size() - (buf - header);
|
||||
char* buf = (char*)&_crc + sizeof(_crc);
|
||||
size_t sz = sizeof(FileMapHeader) - (buf - start);
|
||||
int crc = ClassLoader::crc32(0, buf, (jint)sz);
|
||||
return crc;
|
||||
}
|
||||
|
||||
// This function should only be called during run time with UseSharedSpaces enabled.
|
||||
bool FileMapInfo::FileMapHeader::validate() {
|
||||
bool FileMapHeader::validate() {
|
||||
if (VerifySharedSpaces && compute_crc() != _crc) {
|
||||
fail_continue("Header checksum verification failed.");
|
||||
FileMapInfo::fail_continue("Header checksum verification failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1141,11 +1137,11 @@ bool FileMapInfo::FileMapHeader::validate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_version != current_version()) {
|
||||
if (_version != CURRENT_CDS_ARCHIVE_VERSION) {
|
||||
FileMapInfo::fail_continue("The shared archive file is the wrong version.");
|
||||
return false;
|
||||
}
|
||||
if (_magic != (int)0xf00baba2) {
|
||||
if (_magic != CDS_ARCHIVE_MAGIC) {
|
||||
FileMapInfo::fail_continue("The shared archive file has a bad magic number.");
|
||||
return false;
|
||||
}
|
||||
@ -1221,7 +1217,7 @@ bool FileMapInfo::is_in_shared_region(const void* p, int idx) {
|
||||
idx == MetaspaceShared::mc ||
|
||||
idx == MetaspaceShared::md, "invalid region index");
|
||||
char* base = _header->region_addr(idx);
|
||||
if (p >= base && p < base + _header->_space[idx]._used) {
|
||||
if (p >= base && p < base + space_at(idx)->_used) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1230,7 +1226,7 @@ bool FileMapInfo::is_in_shared_region(const void* p, int idx) {
|
||||
void FileMapInfo::print_shared_spaces() {
|
||||
tty->print_cr("Shared Spaces:");
|
||||
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
|
||||
CDSFileMapRegion* si = space_at(i);
|
||||
char *base = _header->region_addr(i);
|
||||
tty->print(" %s " INTPTR_FORMAT "-" INTPTR_FORMAT,
|
||||
shared_region_name[i],
|
||||
@ -1247,7 +1243,7 @@ void FileMapInfo::stop_sharing_and_unmap(const char* msg) {
|
||||
char *addr = map_info->_header->region_addr(i);
|
||||
if (addr != NULL && !MetaspaceShared::is_heap_region(i)) {
|
||||
map_info->unmap_region(i);
|
||||
map_info->_header->_space[i]._addr._base = NULL;
|
||||
map_info->space_at(i)->_addr._base = NULL;
|
||||
}
|
||||
}
|
||||
// Dealloc the archive heap regions only without unmapping. The regions are part
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define SHARE_VM_MEMORY_FILEMAP_HPP
|
||||
|
||||
#include "classfile/classLoader.hpp"
|
||||
#include "include/cds.h"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/metaspace.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
@ -87,17 +88,86 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct FileMapHeader : public CDSFileMapHeaderBase {
|
||||
size_t _alignment; // how shared archive should be aligned
|
||||
int _obj_alignment; // value of ObjectAlignmentInBytes
|
||||
address _narrow_oop_base; // compressed oop encoding base
|
||||
int _narrow_oop_shift; // compressed oop encoding shift
|
||||
bool _compact_strings; // value of CompactStrings
|
||||
uintx _max_heap_size; // java max heap size during dumping
|
||||
Universe::NARROW_OOP_MODE _narrow_oop_mode; // compressed oop encoding mode
|
||||
int _narrow_klass_shift; // save narrow klass base and shift
|
||||
address _narrow_klass_base;
|
||||
char* _misc_data_patching_start;
|
||||
char* _read_only_tables_start;
|
||||
address _cds_i2i_entry_code_buffers;
|
||||
size_t _cds_i2i_entry_code_buffers_size;
|
||||
size_t _core_spaces_size; // number of bytes allocated by the core spaces
|
||||
// (mc, md, ro, rw and od).
|
||||
|
||||
// The following fields are all sanity checks for whether this archive
|
||||
// will function correctly with this JVM and the bootclasspath it's
|
||||
// invoked with.
|
||||
char _jvm_ident[JVM_IDENT_MAX]; // identifier for jvm
|
||||
|
||||
// The _paths_misc_info is a variable-size structure that records "miscellaneous"
|
||||
// information during dumping. It is generated and validated by the
|
||||
// SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp for
|
||||
// detailed description.
|
||||
//
|
||||
// The _paths_misc_info data is stored as a byte array in the archive file header,
|
||||
// immediately after the _header field. This information is used only when
|
||||
// checking the validity of the archive and is deallocated after the archive is loaded.
|
||||
//
|
||||
// Note that the _paths_misc_info does NOT include information for JAR files
|
||||
// that existed during dump time. Their information is stored in _shared_path_table.
|
||||
int _paths_misc_info_size;
|
||||
|
||||
// The following is a table of all the class path entries that were used
|
||||
// during dumping. At run time, we require these files to exist and have the same
|
||||
// size/modification time, or else the archive will refuse to load.
|
||||
//
|
||||
// All of these entries must be JAR files. The dumping process would fail if a non-empty
|
||||
// directory was specified in the classpaths. If an empty directory was specified
|
||||
// it is checked by the _paths_misc_info as described above.
|
||||
//
|
||||
// FIXME -- if JAR files in the tail of the list were specified but not used during dumping,
|
||||
// they should be removed from this table, to save space and to avoid spurious
|
||||
// loading failures during runtime.
|
||||
int _shared_path_table_size;
|
||||
size_t _shared_path_entry_size;
|
||||
Array<u8>* _shared_path_table;
|
||||
|
||||
jshort _app_class_paths_start_index; // Index of first app classpath entry
|
||||
jshort _app_module_paths_start_index; // Index of first module path entry
|
||||
jshort _max_used_path_index; // max path index referenced during CDS dump
|
||||
bool _verify_local; // BytecodeVerificationLocal setting
|
||||
bool _verify_remote; // BytecodeVerificationRemote setting
|
||||
bool _has_platform_or_app_classes; // Archive contains app classes
|
||||
|
||||
void set_has_platform_or_app_classes(bool v) {
|
||||
_has_platform_or_app_classes = v;
|
||||
}
|
||||
bool has_platform_or_app_classes() { return _has_platform_or_app_classes; }
|
||||
jshort max_used_path_index() { return _max_used_path_index; }
|
||||
jshort app_module_paths_start_index() { return _app_module_paths_start_index; }
|
||||
|
||||
char* region_addr(int idx);
|
||||
|
||||
bool validate();
|
||||
void populate(FileMapInfo* info, size_t alignment);
|
||||
int compute_crc();
|
||||
};
|
||||
|
||||
|
||||
class FileMapInfo : public CHeapObj<mtInternal> {
|
||||
private:
|
||||
friend class ManifestStream;
|
||||
friend class VMStructs;
|
||||
enum {
|
||||
_invalid_version = -1,
|
||||
_current_version = 3
|
||||
};
|
||||
friend struct FileMapHeader;
|
||||
|
||||
bool _file_open;
|
||||
int _fd;
|
||||
bool _file_open;
|
||||
int _fd;
|
||||
size_t _file_offset;
|
||||
|
||||
private:
|
||||
@ -116,100 +186,7 @@ public:
|
||||
// methods, we would get sizeof(FileMapHeaderBase) == 1 with gcc.
|
||||
intx _dummy;
|
||||
};
|
||||
struct FileMapHeader : FileMapHeaderBase {
|
||||
// Use data() and data_size() to memcopy to/from the FileMapHeader. We need to
|
||||
// avoid read/writing the C++ vtable pointer.
|
||||
static size_t data_size() {
|
||||
return sizeof(FileMapHeader) - sizeof(FileMapInfo::FileMapHeaderBase);
|
||||
}
|
||||
char* data() {
|
||||
return ((char*)this) + sizeof(FileMapHeaderBase);
|
||||
}
|
||||
|
||||
int _magic; // identify file type.
|
||||
int _crc; // header crc checksum.
|
||||
int _version; // (from enum, above.)
|
||||
size_t _alignment; // how shared archive should be aligned
|
||||
int _obj_alignment; // value of ObjectAlignmentInBytes
|
||||
address _narrow_oop_base; // compressed oop encoding base
|
||||
int _narrow_oop_shift; // compressed oop encoding shift
|
||||
bool _compact_strings; // value of CompactStrings
|
||||
uintx _max_heap_size; // java max heap size during dumping
|
||||
Universe::NARROW_OOP_MODE _narrow_oop_mode; // compressed oop encoding mode
|
||||
int _narrow_klass_shift; // save narrow klass base and shift
|
||||
address _narrow_klass_base;
|
||||
char* _misc_data_patching_start;
|
||||
char* _read_only_tables_start;
|
||||
address _cds_i2i_entry_code_buffers;
|
||||
size_t _cds_i2i_entry_code_buffers_size;
|
||||
size_t _core_spaces_size; // number of bytes allocated by the core spaces
|
||||
// (mc, md, ro, rw and od).
|
||||
struct space_info {
|
||||
int _crc; // crc checksum of the current space
|
||||
size_t _file_offset; // sizeof(this) rounded to vm page size
|
||||
union {
|
||||
char* _base; // copy-on-write base address
|
||||
intx _offset; // offset from the compressed oop encoding base, only used
|
||||
// by archive heap space
|
||||
} _addr;
|
||||
size_t _used; // for setting space top on read
|
||||
bool _read_only; // read only space?
|
||||
bool _allow_exec; // executable code in space?
|
||||
} _space[MetaspaceShared::n_regions];
|
||||
|
||||
// The following fields are all sanity checks for whether this archive
|
||||
// will function correctly with this JVM and the bootclasspath it's
|
||||
// invoked with.
|
||||
char _jvm_ident[JVM_IDENT_MAX]; // identifier for jvm
|
||||
|
||||
// The _paths_misc_info is a variable-size structure that records "miscellaneous"
|
||||
// information during dumping. It is generated and validated by the
|
||||
// SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp for
|
||||
// detailed description.
|
||||
//
|
||||
// The _paths_misc_info data is stored as a byte array in the archive file header,
|
||||
// immediately after the _header field. This information is used only when
|
||||
// checking the validity of the archive and is deallocated after the archive is loaded.
|
||||
//
|
||||
// Note that the _paths_misc_info does NOT include information for JAR files
|
||||
// that existed during dump time. Their information is stored in _shared_path_table.
|
||||
int _paths_misc_info_size;
|
||||
|
||||
// The following is a table of all the class path entries that were used
|
||||
// during dumping. At run time, we require these files to exist and have the same
|
||||
// size/modification time, or else the archive will refuse to load.
|
||||
//
|
||||
// All of these entries must be JAR files. The dumping process would fail if a non-empty
|
||||
// directory was specified in the classpaths. If an empty directory was specified
|
||||
// it is checked by the _paths_misc_info as described above.
|
||||
//
|
||||
// FIXME -- if JAR files in the tail of the list were specified but not used during dumping,
|
||||
// they should be removed from this table, to save space and to avoid spurious
|
||||
// loading failures during runtime.
|
||||
int _shared_path_table_size;
|
||||
size_t _shared_path_entry_size;
|
||||
Array<u8>* _shared_path_table;
|
||||
|
||||
jshort _app_class_paths_start_index; // Index of first app classpath entry
|
||||
jshort _app_module_paths_start_index; // Index of first module path entry
|
||||
jshort _max_used_path_index; // max path index referenced during CDS dump
|
||||
bool _verify_local; // BytecodeVerificationLocal setting
|
||||
bool _verify_remote; // BytecodeVerificationRemote setting
|
||||
bool _has_platform_or_app_classes; // Archive contains app classes
|
||||
|
||||
void set_has_platform_or_app_classes(bool v) {
|
||||
_has_platform_or_app_classes = v;
|
||||
}
|
||||
bool has_platform_or_app_classes() { return _has_platform_or_app_classes; }
|
||||
jshort max_used_path_index() { return _max_used_path_index; }
|
||||
jshort app_module_paths_start_index() { return _app_module_paths_start_index; }
|
||||
|
||||
char* region_addr(int idx);
|
||||
|
||||
bool validate();
|
||||
void populate(FileMapInfo* info, size_t alignment);
|
||||
int compute_crc();
|
||||
};
|
||||
|
||||
FileMapHeader * _header;
|
||||
|
||||
@ -227,7 +204,6 @@ public:
|
||||
FileMapInfo();
|
||||
~FileMapInfo();
|
||||
|
||||
static int current_version() { return _current_version; }
|
||||
int compute_header_crc() { return _header->compute_crc(); }
|
||||
void set_header_crc(int crc) { _header->_crc = crc; }
|
||||
void populate_header(size_t alignment);
|
||||
@ -278,8 +254,8 @@ public:
|
||||
bool read_only, bool allow_exec);
|
||||
size_t write_archive_heap_regions(GrowableArray<MemRegion> *heap_mem,
|
||||
int first_region_id, int max_num_regions);
|
||||
void write_bytes(const void* buffer, int count);
|
||||
void write_bytes_aligned(const void* buffer, int count);
|
||||
void write_bytes(const void* buffer, size_t count);
|
||||
void write_bytes_aligned(const void* buffer, size_t count);
|
||||
char* map_region(int i, char** top_ret);
|
||||
void map_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
void fixup_mapped_heap_regions() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
@ -332,6 +308,11 @@ public:
|
||||
bool is_open = false) NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
bool verify_mapped_heap_regions(int first, int num) NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
void dealloc_archive_heap_regions(MemRegion* regions, int num) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
CDSFileMapRegion* space_at(int i) {
|
||||
assert(i >= 0 && i < NUM_CDS_REGIONS, "invalid region");
|
||||
return &_header->_space[i];
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_MEMORY_FILEMAP_HPP
|
||||
|
@ -333,7 +333,7 @@ void MetaspaceShared::post_initialize(TRAPS) {
|
||||
int size = FileMapInfo::get_number_of_shared_paths();
|
||||
if (size > 0) {
|
||||
SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD);
|
||||
FileMapInfo::FileMapHeader* header = FileMapInfo::current_info()->header();
|
||||
FileMapHeader* header = FileMapInfo::current_info()->header();
|
||||
ClassLoaderExt::init_paths_start_index(header->_app_class_paths_start_index);
|
||||
ClassLoaderExt::init_app_module_paths_start_index(header->_app_module_paths_start_index);
|
||||
}
|
||||
|
@ -42,17 +42,17 @@ CDSOffsets* CDSOffsets::_all = NULL;
|
||||
#define ADD_NEXT(list, name, value) \
|
||||
list->add_end(new CDSOffsets(name, value, NULL))
|
||||
|
||||
#define CREATE_OFFSET_MAPS \
|
||||
_all = new CDSOffsets("size_t_size", sizeof(size_t), NULL); \
|
||||
ADD_NEXT(_all, "FileMapHeader::_magic", offset_of(FileMapInfo::FileMapHeader, _magic)); \
|
||||
ADD_NEXT(_all, "FileMapHeader::_crc", offset_of(FileMapInfo::FileMapHeader, _crc)); \
|
||||
ADD_NEXT(_all, "FileMapHeader::_version", offset_of(FileMapInfo::FileMapHeader, _version)); \
|
||||
ADD_NEXT(_all, "FileMapHeader::_space[0]", offset_of(FileMapInfo::FileMapHeader, _space)); \
|
||||
ADD_NEXT(_all, "space_info::_crc", offset_of(FileMapInfo::FileMapHeader::space_info, _crc)); \
|
||||
ADD_NEXT(_all, "space_info::_used", offset_of(FileMapInfo::FileMapHeader::space_info, _used)); \
|
||||
ADD_NEXT(_all, "FileMapHeader::_paths_misc_info_size", offset_of(FileMapInfo::FileMapHeader, _paths_misc_info_size)); \
|
||||
ADD_NEXT(_all, "file_header_size", sizeof(FileMapInfo::FileMapHeader)); \
|
||||
ADD_NEXT(_all, "space_info_size", sizeof(FileMapInfo::FileMapHeader::space_info));
|
||||
#define CREATE_OFFSET_MAPS \
|
||||
_all = new CDSOffsets("size_t_size", sizeof(size_t), NULL); \
|
||||
ADD_NEXT(_all, "FileMapHeader::_magic", offset_of(FileMapHeader, _magic)); \
|
||||
ADD_NEXT(_all, "FileMapHeader::_crc", offset_of(FileMapHeader, _crc)); \
|
||||
ADD_NEXT(_all, "FileMapHeader::_version", offset_of(FileMapHeader, _version)); \
|
||||
ADD_NEXT(_all, "FileMapHeader::_space[0]", offset_of(FileMapHeader, _space)); \
|
||||
ADD_NEXT(_all, "CDSFileMapRegion::_crc", offset_of(CDSFileMapRegion, _crc)); \
|
||||
ADD_NEXT(_all, "CDSFileMapRegion::_used", offset_of(CDSFileMapRegion, _used)); \
|
||||
ADD_NEXT(_all, "FileMapHeader::_paths_misc_info_size", offset_of(FileMapHeader, _paths_misc_info_size)); \
|
||||
ADD_NEXT(_all, "file_header_size", sizeof(FileMapHeader)); \
|
||||
ADD_NEXT(_all, "CDSFileMapRegion_size", sizeof(CDSFileMapRegion));
|
||||
|
||||
int CDSOffsets::find_offset(const char* name) {
|
||||
if (_all == NULL) {
|
||||
|
@ -1095,11 +1095,11 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
|
||||
/* FileMapInfo fields (CDS archive related) */ \
|
||||
/********************************************/ \
|
||||
\
|
||||
CDS_ONLY(nonstatic_field(FileMapInfo, _header, FileMapInfo::FileMapHeader*)) \
|
||||
CDS_ONLY( static_field(FileMapInfo, _current_info, FileMapInfo*)) \
|
||||
CDS_ONLY(nonstatic_field(FileMapInfo::FileMapHeader, _space[0], FileMapInfo::FileMapHeader::space_info))\
|
||||
CDS_ONLY(nonstatic_field(FileMapInfo::FileMapHeader::space_info, _addr._base, char*)) \
|
||||
CDS_ONLY(nonstatic_field(FileMapInfo::FileMapHeader::space_info, _used, size_t)) \
|
||||
CDS_ONLY(nonstatic_field(FileMapInfo, _header, FileMapHeader*)) \
|
||||
CDS_ONLY( static_field(FileMapInfo, _current_info, FileMapInfo*)) \
|
||||
CDS_ONLY(nonstatic_field(FileMapHeader, _space[0], CDSFileMapRegion)) \
|
||||
CDS_ONLY(nonstatic_field(CDSFileMapRegion, _addr._base, char*)) \
|
||||
CDS_ONLY(nonstatic_field(CDSFileMapRegion, _used, size_t)) \
|
||||
\
|
||||
/******************/ \
|
||||
/* VMError fields */ \
|
||||
@ -1978,9 +1978,8 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
|
||||
declare_toplevel_type(Annotations*) \
|
||||
declare_type(OopMapValue, StackObj) \
|
||||
declare_type(FileMapInfo, CHeapObj<mtInternal>) \
|
||||
declare_type(FileMapInfo::FileMapHeaderBase, CHeapObj<mtClass>) \
|
||||
declare_type(FileMapInfo::FileMapHeader, FileMapInfo::FileMapHeaderBase)\
|
||||
declare_toplevel_type(FileMapInfo::FileMapHeader::space_info) \
|
||||
declare_toplevel_type(FileMapHeader) \
|
||||
declare_toplevel_type(CDSFileMapRegion) \
|
||||
\
|
||||
/************/ \
|
||||
/* GC types */ \
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <link.h>
|
||||
#include "libproc_impl.h"
|
||||
#include "salibelf.h"
|
||||
#include "cds.h"
|
||||
|
||||
// This file has the libproc implementation to read core files.
|
||||
// For live processes, refer to ps_proc.c. Portions of this is adapted
|
||||
@ -203,65 +204,6 @@ static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) {
|
||||
// PROT_READ pages. These pages are not dumped into core dump.
|
||||
// With this workaround, these pages are read from classes.jsa.
|
||||
|
||||
// FIXME: !HACK ALERT!
|
||||
// The format of sharing achive file header is needed to read shared heap
|
||||
// file mappings. For now, I am hard coding portion of FileMapHeader here.
|
||||
// Refer to filemap.hpp.
|
||||
|
||||
// FileMapHeader describes the shared space data in the file to be
|
||||
// mapped. This structure gets written to a file. It is not a class,
|
||||
// so that the compilers don't add any compiler-private data to it.
|
||||
|
||||
#define NUM_SHARED_MAPS 9
|
||||
|
||||
// Refer to FileMapInfo::_current_version in filemap.hpp
|
||||
#define CURRENT_ARCHIVE_VERSION 3
|
||||
|
||||
typedef unsigned char* address;
|
||||
typedef uintptr_t uintx;
|
||||
typedef intptr_t intx;
|
||||
|
||||
struct FileMapHeader {
|
||||
int _magic; // identify file type.
|
||||
int _crc; // header crc checksum.
|
||||
int _version; // (from enum, above.)
|
||||
size_t _alignment; // how shared archive should be aligned
|
||||
int _obj_alignment; // value of ObjectAlignmentInBytes
|
||||
address _narrow_oop_base; // compressed oop encoding base
|
||||
int _narrow_oop_shift; // compressed oop encoding shift
|
||||
bool _compact_strings; // value of CompactStrings
|
||||
uintx _max_heap_size; // java max heap size during dumping
|
||||
int _narrow_oop_mode; // compressed oop encoding mode
|
||||
int _narrow_klass_shift; // save narrow klass base and shift
|
||||
address _narrow_klass_base;
|
||||
char* _misc_data_patching_start;
|
||||
char* _read_only_tables_start;
|
||||
address _cds_i2i_entry_code_buffers;
|
||||
size_t _cds_i2i_entry_code_buffers_size;
|
||||
size_t _core_spaces_size; // number of bytes allocated by the core spaces
|
||||
// (mc, md, ro, rw and od).
|
||||
|
||||
|
||||
struct space_info {
|
||||
int _crc; // crc checksum of the current space
|
||||
size_t _file_offset; // sizeof(this) rounded to vm page size
|
||||
union {
|
||||
char* _base; // copy-on-write base address
|
||||
intx _offset; // offset from the compressed oop encoding base, only used
|
||||
// by archive heap space
|
||||
} _addr;
|
||||
size_t _used; // for setting space top on read
|
||||
// 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
|
||||
// the C type matching the C++ bool type on any given platform.
|
||||
// We assume the corresponding C type is char but licensees
|
||||
// may need to adjust the type of these fields.
|
||||
char _read_only; // read only space?
|
||||
char _allow_exec; // executable code in space?
|
||||
} _space[NUM_SHARED_MAPS];
|
||||
|
||||
// Ignore the rest of the FileMapHeader. We don't need those fields here.
|
||||
};
|
||||
|
||||
static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) {
|
||||
jboolean i;
|
||||
if (ps_pdread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) {
|
||||
@ -317,7 +259,7 @@ static bool init_classsharing_workaround(struct ps_prochandle* ph) {
|
||||
const char *jvm_name = 0;
|
||||
if ((jvm_name = strstr(lib->name, LIBJVM_NAME)) != 0) {
|
||||
char classes_jsa[PATH_MAX];
|
||||
struct FileMapHeader header;
|
||||
CDSFileMapHeaderBase header;
|
||||
int fd = -1;
|
||||
int m = 0;
|
||||
size_t n = 0;
|
||||
@ -374,34 +316,34 @@ static bool init_classsharing_workaround(struct ps_prochandle* ph) {
|
||||
print_debug("opened %s\n", classes_jsa);
|
||||
}
|
||||
|
||||
// read FileMapHeader from the file
|
||||
memset(&header, 0, sizeof(struct FileMapHeader));
|
||||
if ((n = read(fd, &header, sizeof(struct FileMapHeader)))
|
||||
!= sizeof(struct FileMapHeader)) {
|
||||
// read CDSFileMapHeaderBase from the file
|
||||
memset(&header, 0, sizeof(CDSFileMapHeaderBase));
|
||||
if ((n = read(fd, &header, sizeof(CDSFileMapHeaderBase)))
|
||||
!= sizeof(CDSFileMapHeaderBase)) {
|
||||
print_debug("can't read shared archive file map header from %s\n", classes_jsa);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check file magic
|
||||
if (header._magic != 0xf00baba2) {
|
||||
print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n",
|
||||
classes_jsa, header._magic);
|
||||
if (header._magic != CDS_ARCHIVE_MAGIC) {
|
||||
print_debug("%s has bad shared archive file magic number 0x%x, expecting 0x%x\n",
|
||||
classes_jsa, header._magic, CDS_ARCHIVE_MAGIC);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check version
|
||||
if (header._version != CURRENT_ARCHIVE_VERSION) {
|
||||
if (header._version != CURRENT_CDS_ARCHIVE_VERSION) {
|
||||
print_debug("%s has wrong shared archive file version %d, expecting %d\n",
|
||||
classes_jsa, header._version, CURRENT_ARCHIVE_VERSION);
|
||||
classes_jsa, header._version, CURRENT_CDS_ARCHIVE_VERSION);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
ph->core->classes_jsa_fd = fd;
|
||||
// add read-only maps from classes.jsa to the list of maps
|
||||
for (m = 0; m < NUM_SHARED_MAPS; m++) {
|
||||
for (m = 0; m < NUM_CDS_REGIONS; m++) {
|
||||
if (header._space[m]._read_only) {
|
||||
base = (uintptr_t) header._space[m]._addr._base;
|
||||
// no need to worry about the fractional pages at-the-end.
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include "libproc_impl.h"
|
||||
#include "cds.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext.h"
|
||||
@ -204,66 +205,6 @@ static map_info* core_lookup(struct ps_prochandle *ph, uintptr_t addr) {
|
||||
// PROT_READ pages. These pages are not dumped into core dump.
|
||||
// With this workaround, these pages are read from classes.jsa.
|
||||
|
||||
// FIXME: !HACK ALERT!
|
||||
// The format of sharing achive file header is needed to read shared heap
|
||||
// file mappings. For now, I am hard coding portion of FileMapHeader here.
|
||||
// Refer to filemap.hpp.
|
||||
|
||||
// FileMapHeader describes the shared space data in the file to be
|
||||
// mapped. This structure gets written to a file. It is not a class,
|
||||
// so that the compilers don't add any compiler-private data to it.
|
||||
|
||||
#define NUM_SHARED_MAPS 9
|
||||
|
||||
// Refer to FileMapInfo::_current_version in filemap.hpp
|
||||
#define CURRENT_ARCHIVE_VERSION 3
|
||||
|
||||
typedef unsigned char* address;
|
||||
typedef uintptr_t uintx;
|
||||
typedef intptr_t intx;
|
||||
|
||||
|
||||
struct FileMapHeader {
|
||||
int _magic; // identify file type.
|
||||
int _crc; // header crc checksum.
|
||||
int _version; // (from enum, above.)
|
||||
size_t _alignment; // how shared archive should be aligned
|
||||
int _obj_alignment; // value of ObjectAlignmentInBytes
|
||||
address _narrow_oop_base; // compressed oop encoding base
|
||||
int _narrow_oop_shift; // compressed oop encoding shift
|
||||
bool _compact_strings; // value of CompactStrings
|
||||
uintx _max_heap_size; // java max heap size during dumping
|
||||
int _narrow_oop_mode; // compressed oop encoding mode
|
||||
int _narrow_klass_shift; // save narrow klass base and shift
|
||||
address _narrow_klass_base;
|
||||
char* _misc_data_patching_start;
|
||||
char* _read_only_tables_start;
|
||||
address _cds_i2i_entry_code_buffers;
|
||||
size_t _cds_i2i_entry_code_buffers_size;
|
||||
size_t _core_spaces_size; // number of bytes allocated by the core spaces
|
||||
// (mc, md, ro, rw and od).
|
||||
|
||||
|
||||
struct space_info {
|
||||
int _crc; // crc checksum of the current space
|
||||
size_t _file_offset; // sizeof(this) rounded to vm page size
|
||||
union {
|
||||
char* _base; // copy-on-write base address
|
||||
intx _offset; // offset from the compressed oop encoding base, only used
|
||||
// by archive heap space
|
||||
} _addr;
|
||||
size_t _used; // for setting space top on read
|
||||
// 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
|
||||
// the C type matching the C++ bool type on any given platform.
|
||||
// We assume the corresponding C type is char but licensees
|
||||
// may need to adjust the type of these fields.
|
||||
char _read_only; // read only space?
|
||||
char _allow_exec; // executable code in space?
|
||||
} _space[NUM_SHARED_MAPS];
|
||||
|
||||
// Ignore the rest of the FileMapHeader. We don't need those fields here.
|
||||
};
|
||||
|
||||
static bool read_jboolean(struct ps_prochandle* ph, uintptr_t addr, jboolean* pvalue) {
|
||||
jboolean i;
|
||||
if (ps_pread(ph, (psaddr_t) addr, &i, sizeof(i)) == PS_OK) {
|
||||
@ -326,7 +267,7 @@ static bool init_classsharing_workaround(struct ps_prochandle* ph) {
|
||||
const char *jvm_name = 0;
|
||||
if ((jvm_name = strstr(lib->name, LIBJVM_NAME)) != 0) {
|
||||
char classes_jsa[PATH_MAX];
|
||||
struct FileMapHeader header;
|
||||
CDSFileMapHeaderBase header;
|
||||
int fd = -1;
|
||||
uintptr_t base = 0, useSharedSpacesAddr = 0;
|
||||
uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0;
|
||||
@ -380,34 +321,34 @@ static bool init_classsharing_workaround(struct ps_prochandle* ph) {
|
||||
print_debug("opened %s\n", classes_jsa);
|
||||
}
|
||||
|
||||
// read FileMapHeader from the file
|
||||
memset(&header, 0, sizeof(struct FileMapHeader));
|
||||
if ((n = read(fd, &header, sizeof(struct FileMapHeader)))
|
||||
!= sizeof(struct FileMapHeader)) {
|
||||
// read CDSFileMapHeaderBase from the file
|
||||
memset(&header, 0, sizeof(CDSFileMapHeaderBase));
|
||||
if ((n = read(fd, &header, sizeof(CDSFileMapHeaderBase)))
|
||||
!= sizeof(CDSFileMapHeaderBase)) {
|
||||
print_debug("can't read shared archive file map header from %s\n", classes_jsa);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check file magic
|
||||
if (header._magic != 0xf00baba2) {
|
||||
print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n",
|
||||
classes_jsa, header._magic);
|
||||
if (header._magic != CDS_ARCHIVE_MAGIC) {
|
||||
print_debug("%s has bad shared archive file magic number 0x%x, expecting 0x%x\n",
|
||||
classes_jsa, header._magic, CDS_ARCHIVE_MAGIC);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check version
|
||||
if (header._version != CURRENT_ARCHIVE_VERSION) {
|
||||
if (header._version != CURRENT_CDS_ARCHIVE_VERSION) {
|
||||
print_debug("%s has wrong shared archive file version %d, expecting %d\n",
|
||||
classes_jsa, header._version, CURRENT_ARCHIVE_VERSION);
|
||||
classes_jsa, header._version, CURRENT_CDS_ARCHIVE_VERSION);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
ph->core->classes_jsa_fd = fd;
|
||||
// add read-only maps from classes.jsa to the list of maps
|
||||
for (m = 0; m < NUM_SHARED_MAPS; m++) {
|
||||
for (m = 0; m < NUM_CDS_REGIONS; m++) {
|
||||
if (header._space[m]._read_only) {
|
||||
base = (uintptr_t) header._space[m]._addr._base;
|
||||
// no need to worry about the fractional pages at-the-end.
|
||||
|
@ -63,13 +63,13 @@ public class FileMapInfo {
|
||||
headerValue = headerAddress.getAddressAt(0);
|
||||
|
||||
// FileMapHeader
|
||||
type = db.lookupType("FileMapInfo::FileMapHeader");
|
||||
type = db.lookupType("FileMapHeader");
|
||||
AddressField spaceField = type.getAddressField("_space[0]");
|
||||
Address spaceValue = headerValue.addOffsetTo(type.getField("_space[0]").getOffset());
|
||||
mdSpaceValue = spaceValue.addOffsetTo(3 * spaceField.getSize());
|
||||
|
||||
// SpaceInfo
|
||||
type = db.lookupType("FileMapInfo::FileMapHeader::space_info");
|
||||
type = db.lookupType("CDSFileMapRegion");
|
||||
long mdRegionBaseAddressOffset = type.getField("_addr._base").getOffset();
|
||||
mdRegionBaseAddress = (mdSpaceValue.addOffsetTo(mdRegionBaseAddressOffset)).getAddressAt(0);
|
||||
long mdRegionSizeOffset = type.getField("_used").getOffset();
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "cds.h"
|
||||
|
||||
#define CHECK_EXCEPTION_(value) if(env->ExceptionOccurred()) { return value; }
|
||||
#define CHECK_EXCEPTION if(env->ExceptionOccurred()) { return;}
|
||||
@ -173,7 +174,7 @@ static void detach_internal(JNIEnv* env, jobject this_obj) {
|
||||
int classes_jsa_fd = env->GetIntField(this_obj, classes_jsa_fd_ID);
|
||||
if (classes_jsa_fd != -1) {
|
||||
close(classes_jsa_fd);
|
||||
struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID);
|
||||
CDSFileMapHeaderBase* pheader = (CDSFileMapHeaderBase*) env->GetLongField(this_obj, p_file_map_header_ID);
|
||||
if (pheader != NULL) {
|
||||
free(pheader);
|
||||
}
|
||||
@ -484,67 +485,13 @@ wrapper_fill_cframe_list(void *cd, const prgregset_t regs, uint_t argc,
|
||||
return(fill_cframe_list(cd, regs, argc, argv));
|
||||
}
|
||||
|
||||
// part of the class sharing workaround
|
||||
|
||||
// FIXME: !!HACK ALERT!!
|
||||
|
||||
// The format of sharing achive file header is needed to read shared heap
|
||||
// file mappings. For now, I am hard coding portion of FileMapHeader here.
|
||||
// Refer to filemap.hpp.
|
||||
|
||||
// FileMapHeader describes the shared space data in the file to be
|
||||
// mapped. This structure gets written to a file. It is not a class, so
|
||||
// that the compilers don't add any compiler-private data to it.
|
||||
|
||||
const int NUM_SHARED_MAPS = 9;
|
||||
|
||||
// Refer to FileMapInfo::_current_version in filemap.hpp
|
||||
const int CURRENT_ARCHIVE_VERSION = 3;
|
||||
|
||||
typedef unsigned char* address;
|
||||
typedef uintptr_t uintx;
|
||||
typedef intptr_t intx;
|
||||
|
||||
struct FileMapHeader {
|
||||
int _magic; // identify file type.
|
||||
int _crc; // header crc checksum.
|
||||
int _version; // (from enum, above.)
|
||||
size_t _alignment; // how shared archive should be aligned
|
||||
int _obj_alignment; // value of ObjectAlignmentInBytes
|
||||
address _narrow_oop_base; // compressed oop encoding base
|
||||
int _narrow_oop_shift; // compressed oop encoding shift
|
||||
bool _compact_strings; // value of CompactStrings
|
||||
uintx _max_heap_size; // java max heap size during dumping
|
||||
int _narrow_oop_mode; // compressed oop encoding mode
|
||||
int _narrow_klass_shift; // save narrow klass base and shift
|
||||
address _narrow_klass_base;
|
||||
char* _misc_data_patching_start;
|
||||
char* _read_only_tables_start;
|
||||
address _cds_i2i_entry_code_buffers;
|
||||
size_t _cds_i2i_entry_code_buffers_size;
|
||||
size_t _core_spaces_size; // number of bytes allocated by the core spaces
|
||||
// (mc, md, ro, rw and od).
|
||||
|
||||
|
||||
struct space_info {
|
||||
int _crc; // crc checksum of the current space
|
||||
size_t _file_offset; // sizeof(this) rounded to vm page size
|
||||
union {
|
||||
char* _base; // copy-on-write base address
|
||||
intx _offset; // offset from the compressed oop encoding base, only used
|
||||
// by archive heap space
|
||||
} _addr;
|
||||
size_t _used; // for setting space top on read
|
||||
// 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
|
||||
// the C type matching the C++ bool type on any given platform.
|
||||
// We assume the corresponding C type is char but licensees
|
||||
// may need to adjust the type of these fields.
|
||||
char _read_only; // read only space?
|
||||
char _allow_exec; // executable code in space?
|
||||
} _space[NUM_SHARED_MAPS];
|
||||
|
||||
// Ignore the rest of the FileMapHeader. We don't need those fields here.
|
||||
};
|
||||
//---------------------------------------------------------------
|
||||
// Part of the class sharing workaround:
|
||||
//
|
||||
// With class sharing, pages are mapped from classes.jsa file.
|
||||
// The read-only class sharing pages are mapped as MAP_SHARED,
|
||||
// PROT_READ pages. These pages are not dumped into core dump.
|
||||
// With this workaround, these pages are read from classes.jsa.
|
||||
|
||||
static bool
|
||||
read_jboolean(struct ps_prochandle* ph, psaddr_t addr, jboolean* pvalue) {
|
||||
@ -662,16 +609,16 @@ init_classsharing_workaround(void *cd, const prmap_t* pmap, const char* obj_name
|
||||
}
|
||||
|
||||
// parse classes.jsa
|
||||
struct FileMapHeader* pheader = (struct FileMapHeader*) malloc(sizeof(struct FileMapHeader));
|
||||
CDSFileMapHeaderBase* pheader = (CDSFileMapHeaderBase*) malloc(sizeof(CDSFileMapHeaderBase));
|
||||
if (pheader == NULL) {
|
||||
close(fd);
|
||||
THROW_NEW_DEBUGGER_EXCEPTION_("can't allocate memory for shared file map header", 1);
|
||||
}
|
||||
|
||||
memset(pheader, 0, sizeof(struct FileMapHeader));
|
||||
// read FileMapHeader
|
||||
size_t n = read(fd, pheader, sizeof(struct FileMapHeader));
|
||||
if (n != sizeof(struct FileMapHeader)) {
|
||||
memset(pheader, 0, sizeof(CDSFileMapHeaderBase));
|
||||
// read CDSFileMapHeaderBase
|
||||
size_t n = read(fd, pheader, sizeof(CDSFileMapHeaderBase));
|
||||
if (n != sizeof(CDSFileMapHeaderBase)) {
|
||||
char errMsg[ERR_MSG_SIZE];
|
||||
sprintf(errMsg, "unable to read shared archive file map header from %s", classes_jsa);
|
||||
close(fd);
|
||||
@ -680,27 +627,27 @@ init_classsharing_workaround(void *cd, const prmap_t* pmap, const char* obj_name
|
||||
}
|
||||
|
||||
// check file magic
|
||||
if (pheader->_magic != 0xf00baba2) {
|
||||
if (pheader->_magic != CDS_ARCHIVE_MAGIC) {
|
||||
char errMsg[ERR_MSG_SIZE];
|
||||
sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0xf00baba2",
|
||||
classes_jsa, pheader->_magic);
|
||||
sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0x%x",
|
||||
classes_jsa, pheader->_magic, CDS_ARCHIVE_MAGIC);
|
||||
close(fd);
|
||||
free(pheader);
|
||||
THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
|
||||
}
|
||||
|
||||
// check version
|
||||
if (pheader->_version != CURRENT_ARCHIVE_VERSION) {
|
||||
if (pheader->_version != CURRENT_CDS_ARCHIVE_VERSION) {
|
||||
char errMsg[ERR_MSG_SIZE];
|
||||
sprintf(errMsg, "%s has wrong shared archive version %d, expecting %d",
|
||||
classes_jsa, pheader->_version, CURRENT_ARCHIVE_VERSION);
|
||||
classes_jsa, pheader->_version, CURRENT_CDS_ARCHIVE_VERSION);
|
||||
close(fd);
|
||||
free(pheader);
|
||||
THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
|
||||
}
|
||||
|
||||
if (_libsaproc_debug) {
|
||||
for (int m = 0; m < NUM_SHARED_MAPS; m++) {
|
||||
for (int m = 0; m < NUM_CDS_REGIONS; m++) {
|
||||
print_debug("shared file offset %d mapped at 0x%lx, size = %ld, read only? = %d\n",
|
||||
pheader->_space[m]._file_offset, pheader->_space[m]._addr._base,
|
||||
pheader->_space[m]._used, pheader->_space[m]._read_only);
|
||||
@ -1091,10 +1038,10 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLoca
|
||||
if (classes_jsa_fd != -1 && address != (jlong)0) {
|
||||
print_debug("read failed at 0x%lx, attempting shared heap area\n", (long) address);
|
||||
|
||||
struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID);
|
||||
CDSFileMapHeaderBase* pheader = (CDSFileMapHeaderBase*) env->GetLongField(this_obj, p_file_map_header_ID);
|
||||
// walk through the shared mappings -- we just have 9 of them.
|
||||
// so, linear walking is okay.
|
||||
for (int m = 0; m < NUM_SHARED_MAPS; m++) {
|
||||
for (int m = 0; m < NUM_CDS_REGIONS; m++) {
|
||||
|
||||
// We can skip the non-read-only maps. These are mapped as MAP_PRIVATE
|
||||
// and hence will be read by libproc. Besides, the file copy may be
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -62,11 +62,11 @@ import sun.hotspot.WhiteBox;
|
||||
public class SharedArchiveConsistency {
|
||||
public static WhiteBox wb;
|
||||
public static int offset_magic; // FileMapHeader::_magic
|
||||
public static int sp_offset_crc; // FileMapHeader::space_info::_crc
|
||||
public static int sp_offset_crc; // CDSFileMapRegion::_crc
|
||||
public static int file_header_size = -1;// total size of header, variant, need calculation
|
||||
public static int space_info_size; // size of space_info
|
||||
public static int sp_offset; // offset of FileMapHeader::space_info
|
||||
public static int sp_used_offset; // offset of space_info::_used
|
||||
public static int CDSFileMapRegion_size; // size of CDSFileMapRegion
|
||||
public static int sp_offset; // offset of CDSFileMapRegion
|
||||
public static int sp_used_offset; // offset of CDSFileMapRegion::_used
|
||||
public static int size_t_size; // size of size_t
|
||||
|
||||
public static File jsa; // will be updated during test
|
||||
@ -83,7 +83,7 @@ public class SharedArchiveConsistency {
|
||||
public static void getFileOffsetInfo() throws Exception {
|
||||
wb = WhiteBox.getWhiteBox();
|
||||
offset_magic = wb.getOffsetForName("FileMapHeader::_magic");
|
||||
sp_offset_crc = wb.getOffsetForName("space_info::_crc");
|
||||
sp_offset_crc = wb.getOffsetForName("CDSFileMapRegion::_crc");
|
||||
try {
|
||||
int nonExistOffset = wb.getOffsetForName("FileMapHeader::_non_exist_offset");
|
||||
System.exit(-1); // should fail
|
||||
@ -92,9 +92,9 @@ public class SharedArchiveConsistency {
|
||||
}
|
||||
|
||||
sp_offset = wb.getOffsetForName("FileMapHeader::_space[0]") - offset_magic;
|
||||
sp_used_offset = wb.getOffsetForName("space_info::_used") - sp_offset_crc;
|
||||
sp_used_offset = wb.getOffsetForName("CDSFileMapRegion::_used") - sp_offset_crc;
|
||||
size_t_size = wb.getOffsetForName("size_t_size");
|
||||
space_info_size = wb.getOffsetForName("space_info_size");
|
||||
CDSFileMapRegion_size = wb.getOffsetForName("CDSFileMapRegion_size");
|
||||
}
|
||||
|
||||
public static int getFileHeaderSize(FileChannel fc) throws Exception {
|
||||
@ -166,7 +166,7 @@ public class SharedArchiveConsistency {
|
||||
System.out.printf("%-12s%-12s%-12s%-12s%-12s\n", "Space Name", "Offset", "Used bytes", "Reg Start", "Random Offset");
|
||||
start0 = getFileHeaderSize(fc);
|
||||
for (int i = 0; i < num_regions; i++) {
|
||||
used_offset = sp_offset + space_info_size * i + sp_used_offset;
|
||||
used_offset = sp_offset + CDSFileMapRegion_size * i + sp_used_offset;
|
||||
// read 'used'
|
||||
used[i] = readInt(fc, used_offset, size_t_size);
|
||||
start = start0;
|
||||
@ -199,7 +199,7 @@ public class SharedArchiveConsistency {
|
||||
long[] used = new long[num_regions];
|
||||
System.out.printf("%-12s%-12s\n", "Space name", "Used bytes");
|
||||
for (int i = 0; i < num_regions; i++) {
|
||||
used_offset = sp_offset + space_info_size* i + sp_used_offset;
|
||||
used_offset = sp_offset + CDSFileMapRegion_size* i + sp_used_offset;
|
||||
// read 'used'
|
||||
used[i] = readInt(fc, used_offset, size_t_size);
|
||||
System.out.printf("%-12s%-12d\n", shared_region_name[i], used[i]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user