< prev index next > src/hotspot/share/cds/filemap.cpp
Print this page
_compressed_oops = UseCompressedOops;
_compressed_class_ptrs = UseCompressedClassPointers;
_use_secondary_supers_table = UseSecondarySupersTable;
_max_heap_size = MaxHeapSize;
_use_optimized_module_handling = CDSConfig::is_using_optimized_module_handling();
+ _has_aot_linked_classes = CDSConfig::is_dumping_aot_linked_classes();
_has_full_module_graph = CDSConfig::is_dumping_full_module_graph();
+ _has_archived_invokedynamic = CDSConfig::is_dumping_invokedynamic();
+ _has_archived_packages = CDSConfig::is_dumping_packages();
+ _has_archived_protection_domains = CDSConfig::is_dumping_protection_domains();
+ _gc_kind = (int)Universe::heap()->kind();
+ jio_snprintf(_gc_name, sizeof(_gc_name), Universe::heap()->name());
// The following fields are for sanity checks for whether this archive
// will function correctly with this JVM and the bootclasspath it's
// invoked with.
st->print_cr("- _rw_ptrmap_start_pos: " SIZE_FORMAT, _rw_ptrmap_start_pos);
st->print_cr("- _ro_ptrmap_start_pos: " SIZE_FORMAT, _ro_ptrmap_start_pos);
st->print_cr("- allow_archiving_with_java_agent:%d", _allow_archiving_with_java_agent);
st->print_cr("- use_optimized_module_handling: %d", _use_optimized_module_handling);
st->print_cr("- has_full_module_graph %d", _has_full_module_graph);
+ st->print_cr("- has_aot_linked_classes %d", _has_aot_linked_classes);
+ st->print_cr("- has_archived_invokedynamic %d", _has_archived_invokedynamic);
+ st->print_cr("- has_archived_packages %d", _has_archived_packages);
+ st->print_cr("- has_archived_protection_domains %d", _has_archived_protection_domains);
+ st->print_cr("- ptrmap_size_in_bits: " SIZE_FORMAT, _ptrmap_size_in_bits);
}
void SharedClassPathEntry::init_as_non_existent(const char* path, TRAPS) {
_type = non_existent_entry;
set_name(path, CHECK);
return 0;
}
}
int FileMapInfo::get_module_shared_path_index(Symbol* location) {
+ if (location == nullptr) {
+ return 0; // Used by java/lang/reflect/Proxy$ProxyBuilder
+ }
if (location->starts_with("jrt:", 4) && get_number_of_shared_paths() > 0) {
assert(shared_path(0)->is_modules_image(), "first shared_path must be the modules image");
return 0;
}
}
return false;
}
}
! validate_non_existent_class_paths();
_validating_shared_path_table = false;
#if INCLUDE_JVMTI
if (_classpath_entries_for_jvmti != nullptr) {
}
return false;
}
}
! if (!validate_non_existent_class_paths()) {
+ return false;
+ }
_validating_shared_path_table = false;
#if INCLUDE_JVMTI
if (_classpath_entries_for_jvmti != nullptr) {
#endif
return true;
}
! void FileMapInfo::validate_non_existent_class_paths() {
// All of the recorded non-existent paths came from the Class-Path: attribute from the JAR
// files on the app classpath. If any of these are found to exist during runtime,
// it will change how classes are loading for the app loader. For safety, disable
// loading of archived platform/app classes (currently there's no way to disable just the
// app classes).
#endif
return true;
}
! bool FileMapInfo::validate_non_existent_class_paths() {
// All of the recorded non-existent paths came from the Class-Path: attribute from the JAR
// files on the app classpath. If any of these are found to exist during runtime,
// it will change how classes are loading for the app loader. For safety, disable
// loading of archived platform/app classes (currently there's no way to disable just the
// app classes).
for (int i = header()->app_module_paths_start_index() + header()->num_module_paths();
i < get_number_of_shared_paths();
i++) {
SharedClassPathEntry* ent = shared_path(i);
if (!ent->check_non_existent()) {
! log_warning(cds)("Archived non-system classes are disabled because the "
! "file %s exists", ent->name());
! header()->set_has_platform_or_app_classes(false);
}
}
}
// A utility class for reading/validating the GenericCDSFileMapHeader portion of
// a CDS archive's header. The file header of all CDS archives with versions from
// CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION (12) are guaranteed to always start
for (int i = header()->app_module_paths_start_index() + header()->num_module_paths();
i < get_number_of_shared_paths();
i++) {
SharedClassPathEntry* ent = shared_path(i);
if (!ent->check_non_existent()) {
! if (header()->has_aot_linked_classes()) {
! log_error(cds)("CDS archive has aot-linked classes. It cannot be used because the "
! "file %s exists", ent->name());
+ return false;
+ } else {
+ log_warning(cds)("Archived non-system classes are disabled because the "
+ "file %s exists", ent->name());
+ header()->set_has_platform_or_app_classes(false);
+ }
}
}
+
+ return true;
}
// A utility class for reading/validating the GenericCDSFileMapHeader portion of
// a CDS archive's header. The file header of all CDS archives with versions from
// CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION (12) are guaranteed to always start
return true;
}
static const char* region_name(int region_index) {
static const char* names[] = {
! "rw", "ro", "bm", "hp"
};
const int num_regions = sizeof(names)/sizeof(names[0]);
assert(0 <= region_index && region_index < num_regions, "sanity");
return names[region_index];
return true;
}
static const char* region_name(int region_index) {
static const char* names[] = {
! "rw", "ro", "bm", "hp", "cc",
};
const int num_regions = sizeof(names)/sizeof(names[0]);
assert(0 <= region_index && region_index < num_regions, "sanity");
return names[region_index];
if (size > 0) {
log_info(cds)("Shared file region (%s) %d: " SIZE_FORMAT_W(8)
" bytes, addr " INTPTR_FORMAT " file offset 0x%08" PRIxPTR
" crc 0x%08x",
region_name(region), region, size, p2i(requested_base), _file_offset, crc);
+ } else {
+ log_info(cds)("Shared file region (%s) %d: " SIZE_FORMAT_W(8)
+ " bytes", region_name(region), region, size);
}
r->init(region, mapping_offset, size, read_only, allow_exec, crc);
if (base != nullptr) {
assert(map->size() <= old_size, "sanity");
return first_set;
}
! char* FileMapInfo::write_bitmap_region(CHeapBitMap* rw_ptrmap, CHeapBitMap* ro_ptrmap, ArchiveHeapInfo* heap_info,
size_t &size_in_bytes) {
size_t removed_rw_leading_zeros = remove_bitmap_zeros(rw_ptrmap);
size_t removed_ro_leading_zeros = remove_bitmap_zeros(ro_ptrmap);
header()->set_rw_ptrmap_start_pos(removed_rw_leading_zeros);
header()->set_ro_ptrmap_start_pos(removed_ro_leading_zeros);
! size_in_bytes = rw_ptrmap->size_in_bytes() + ro_ptrmap->size_in_bytes();
if (heap_info->is_used()) {
// Remove leading and trailing zeros
size_t removed_oop_leading_zeros = remove_bitmap_zeros(heap_info->oopmap());
size_t removed_ptr_leading_zeros = remove_bitmap_zeros(heap_info->ptrmap());
assert(map->size() <= old_size, "sanity");
return first_set;
}
! char* FileMapInfo::write_bitmap_region(CHeapBitMap* rw_ptrmap, CHeapBitMap* ro_ptrmap,
+ CHeapBitMap* cc_ptrmap,
+ ArchiveHeapInfo* heap_info,
size_t &size_in_bytes) {
size_t removed_rw_leading_zeros = remove_bitmap_zeros(rw_ptrmap);
size_t removed_ro_leading_zeros = remove_bitmap_zeros(ro_ptrmap);
header()->set_rw_ptrmap_start_pos(removed_rw_leading_zeros);
header()->set_ro_ptrmap_start_pos(removed_ro_leading_zeros);
! size_in_bytes = rw_ptrmap->size_in_bytes() + ro_ptrmap->size_in_bytes() + cc_ptrmap->size_in_bytes();
if (heap_info->is_used()) {
// Remove leading and trailing zeros
size_t removed_oop_leading_zeros = remove_bitmap_zeros(heap_info->oopmap());
size_t removed_ptr_leading_zeros = remove_bitmap_zeros(heap_info->ptrmap());
written = write_bitmap(rw_ptrmap, buffer, written);
region_at(MetaspaceShared::ro)->init_ptrmap(written, ro_ptrmap->size());
written = write_bitmap(ro_ptrmap, buffer, written);
+ region_at(MetaspaceShared::cc)->init_ptrmap(written, cc_ptrmap->size());
+ written = write_bitmap(cc_ptrmap, buffer, written);
+
if (heap_info->is_used()) {
FileMapRegion* r = region_at(MetaspaceShared::hp);
r->init_oopmap(written, heap_info->oopmap()->size());
written = write_bitmap(heap_info->oopmap(), buffer, written);
r->set_read_only(false);
return true;
}
// Memory map a region in the address space.
! static const char* shared_region_name[] = { "ReadWrite", "ReadOnly", "Bitmap", "Heap" };
MapArchiveResult FileMapInfo::map_regions(int regions[], int num_regions, char* mapped_base_address, ReservedSpace rs) {
DEBUG_ONLY(FileMapRegion* last_region = nullptr);
intx addr_delta = mapped_base_address - header()->requested_base_address();
r->set_read_only(false);
return true;
}
// Memory map a region in the address space.
! static const char* shared_region_name[] = { "ReadWrite", "ReadOnly", "Bitmap", "Heap", "Code" };
MapArchiveResult FileMapInfo::map_regions(int regions[], int num_regions, char* mapped_base_address, ReservedSpace rs) {
DEBUG_ONLY(FileMapRegion* last_region = nullptr);
intx addr_delta = mapped_base_address - header()->requested_base_address();
}
} else {
// Note that this may either be a "fresh" mapping into unreserved address
// space (Windows, first mapping attempt), or a mapping into pre-reserved
// space (Posix). See also comment in MetaspaceShared::map_archives().
char* base = map_memory(_fd, _full_path, r->file_offset(),
! requested_addr, size, r->read_only(),
r->allow_exec(), mtClassShared);
if (base != requested_addr) {
log_info(cds)("Unable to map %s shared space at " INTPTR_FORMAT,
shared_region_name[i], p2i(requested_addr));
_memory_mapping_failed = true;
}
} else {
// Note that this may either be a "fresh" mapping into unreserved address
// space (Windows, first mapping attempt), or a mapping into pre-reserved
// space (Posix). See also comment in MetaspaceShared::map_archives().
+ bool read_only = r->read_only() && !CDSConfig::is_dumping_final_static_archive();
char* base = map_memory(_fd, _full_path, r->file_offset(),
! requested_addr, size, read_only,
r->allow_exec(), mtClassShared);
if (base != requested_addr) {
log_info(cds)("Unable to map %s shared space at " INTPTR_FORMAT,
shared_region_name[i], p2i(requested_addr));
_memory_mapping_failed = true;
MetaspaceShared::bm, p2i(r->mapped_base()), p2i(r->mapped_end()),
shared_region_name[MetaspaceShared::bm]);
return bitmap_base;
}
+ bool FileMapInfo::map_cached_code_region(ReservedSpace rs) {
+ FileMapRegion* r = region_at(MetaspaceShared::cc);
+ assert(r->used() > 0 && rs.size(), "must be");
+
+ bool read_only = false, allow_exec = true;
+ char* requested_base = rs.base();
+ char* mapped_base = map_memory(_fd, _full_path, r->file_offset(),
+ requested_base, r->used_aligned(), read_only, allow_exec, mtClassShared);
+ if (mapped_base == nullptr) {
+ log_info(cds)("failed to map cached code region");
+ return false;
+ } else {
+ assert(mapped_base == requested_base, "must be");
+ r->set_mapped_from_file(true);
+ r->set_mapped_base(mapped_base);
+ relocate_pointers_in_cached_code_region();
+ log_info(cds)("Mapped static region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT " (%s)",
+ MetaspaceShared::bm, p2i(r->mapped_base()), p2i(r->mapped_end()),
+ shared_region_name[MetaspaceShared::cc]);
+ return true;
+ }
+ }
+
+ class CachedCodeRelocator: public BitMapClosure {
+ address _code_requested_base;
+ address* _patch_base;
+ intx _code_delta;
+ intx _metadata_delta;
+
+ public:
+ CachedCodeRelocator(address code_requested_base, address code_mapped_base,
+ intx metadata_delta) {
+ _code_requested_base = code_requested_base;
+ _patch_base = (address*)code_mapped_base;
+ _code_delta = code_mapped_base - code_requested_base;
+ _metadata_delta = metadata_delta;
+ }
+
+ bool do_bit(size_t offset) {
+ address* p = _patch_base + offset;
+ address requested_ptr = *p;
+ if (requested_ptr < _code_requested_base) {
+ *p = requested_ptr + _metadata_delta;
+ } else {
+ *p = requested_ptr + _code_delta;
+ }
+ return true; // keep iterating
+ }
+ };
+
+ void FileMapInfo::relocate_pointers_in_cached_code_region() {
+ FileMapRegion* r = region_at(MetaspaceShared::cc);
+ char* bitmap_base = map_bitmap_region();
+
+ BitMapView cc_ptrmap = ptrmap_view(MetaspaceShared::cc);
+ if (cc_ptrmap.size() == 0) {
+ return;
+ }
+
+ address core_regions_requested_base = (address)header()->requested_base_address();
+ address core_regions_mapped_base = (address)header()->mapped_base_address();
+ address cc_region_requested_base = core_regions_requested_base + r->mapping_offset();
+ address cc_region_mapped_base = (address)r->mapped_base();
+
+ size_t max_bits_for_core_regions = pointer_delta(mapped_end(), mapped_base(), // FIXME - renamed to core_regions_mapped_base(), etc
+ sizeof(address));
+
+ CachedCodeRelocator patcher(cc_region_requested_base, cc_region_mapped_base,
+ core_regions_mapped_base - core_regions_requested_base);
+ cc_ptrmap.iterate(&patcher);
+ }
+
// This is called when we cannot map the archive at the requested[ base address (usually 0x800000000).
// We relocate all pointers in the 2 core regions (ro, rw).
bool FileMapInfo::relocate_pointers_in_core_regions(intx addr_delta) {
log_debug(cds, reloc)("runtime archive relocation start");
char* bitmap_base = map_bitmap_region();
}
}
}
if (!success) {
! CDSConfig::stop_using_full_module_graph();
}
}
bool FileMapInfo::can_use_heap_region() {
if (!has_heap_region()) {
}
}
}
if (!success) {
! if (CDSConfig::is_using_aot_linked_classes() && !CDSConfig::is_dumping_final_static_archive()) {
+ // It's too later to recover -- we have already committed to use the archived metaspace objects, but
+ // the archived heap objects cannot be loaded, so we don't have the archived FMG to guarantee that
+ // all AOT-linked classes are visible.
+ //
+ // We get here because the heap is too small. The app will fail anyway. So let's quit.
+ MetaspaceShared::unrecoverable_loading_error("CDS archive has aot-linked classes but the archived "
+ "heap objects cannot be loaded. Try increasing your heap size.");
+ }
+ CDSConfig::stop_using_full_module_graph("archive heap loading failed");
}
}
bool FileMapInfo::can_use_heap_region() {
if (!has_heap_region()) {
}
return true;
}
+ bool FileMapInfo::validate_aot_class_linking() {
+ // These checks need to be done after FileMapInfo::initialize(), which gets called before Universe::heap()
+ // is available.
+ if (header()->has_aot_linked_classes()) {
+ CDSConfig::set_has_aot_linked_classes(is_static(), true);
+ if (JvmtiExport::should_post_class_file_load_hook()) {
+ log_error(cds)("CDS archive has aot-linked classes. It cannot be used when JVMTI ClassFileLoadHook is in use.");
+ return false;
+ }
+ if (JvmtiExport::has_early_vmstart_env()) {
+ log_error(cds)("CDS archive has aot-linked classes. It cannot be used when JVMTI early vm start is in use.");
+ return false;
+ }
+ if (!CDSConfig::is_using_full_module_graph() && !CDSConfig::is_dumping_final_static_archive()) {
+ log_error(cds)("CDS archive has aot-linked classes. It cannot be used when archived full module graph is not used.");
+ return false;
+ }
+ if (header()->gc_kind() != (int)Universe::heap()->kind()) {
+ log_error(cds)("CDS archive has aot-linked classes. It cannot be used because GC used during dump time (%s) is not the same as runtime (%s)",
+ header()->gc_name(), Universe::heap()->name());
+ return false;
+ }
+ }
+
+ return true;
+ }
+
// The 2 core spaces are RW->RO
FileMapRegion* FileMapInfo::first_core_region() const {
return region_at(MetaspaceShared::rw);
}
if (!_use_optimized_module_handling) {
CDSConfig::stop_using_optimized_module_handling();
log_info(cds)("optimized module handling: disabled because archive was created without optimized module handling");
}
! if (is_static() && !_has_full_module_graph) {
// Only the static archive can contain the full module graph.
! CDSConfig::stop_using_full_module_graph("archive was created without full module graph");
}
return true;
}
if (!_use_optimized_module_handling) {
CDSConfig::stop_using_optimized_module_handling();
log_info(cds)("optimized module handling: disabled because archive was created without optimized module handling");
}
! if (is_static()) {
// Only the static archive can contain the full module graph.
! if (!_has_full_module_graph) {
+ CDSConfig::stop_using_full_module_graph("archive was created without full module graph");
+ }
+
+ if (_has_archived_invokedynamic) {
+ CDSConfig::set_has_archived_invokedynamic();
+ }
+ if (_has_archived_packages) {
+ CDSConfig::set_is_loading_packages();
+ }
+ if (_has_archived_protection_domains) {
+ CDSConfig::set_is_loading_protection_domains();
+ }
}
return true;
}
< prev index next >