< prev index next >
src/share/vm/memory/metaspaceShared.cpp
Print this page
@@ -32,10 +32,15 @@
#include "classfile/symbolTable.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "code/codeCache.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1Allocator.inline.hpp"
+#include "gc/g1/g1CollectedHeap.hpp"
+#include "gc/g1/g1SATBCardTableModRefBS.hpp"
+#endif
#include "gc/shared/gcLocker.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "interpreter/bytecodes.hpp"
#include "logging/log.hpp"
#include "logging/logMessage.hpp"
@@ -66,10 +71,11 @@
VirtualSpace MetaspaceShared::_shared_vs;
MetaspaceSharedStats MetaspaceShared::_stats;
bool MetaspaceShared::_has_error_classes;
bool MetaspaceShared::_archive_loading_failed = false;
bool MetaspaceShared::_remapped_readwrite = false;
+bool MetaspaceShared::_open_archive_heap_region_mapped = false;
address MetaspaceShared::_cds_i2i_entry_code_buffers = NULL;
size_t MetaspaceShared::_cds_i2i_entry_code_buffers_size = 0;
size_t MetaspaceShared::_core_spaces_size = 0;
// The CDS archive is divided into the following regions:
@@ -77,14 +83,16 @@
// rw - read-write metadata
// ro - read-only metadata and read-only tables
// md - misc data (the c++ vtables)
// od - optional data (original class files)
//
-// s0 - shared strings #0
-// s1 - shared strings #1 (may be empty)
+// s0 - shared strings(closed archive heap space) #0
+// s1 - shared strings(closed archive heap space) #1 (may be empty)
+// oa0 - open archive heap space #0
+// oa1 - open archive heap space #1 (may be empty)
//
-// Except for the s0/s1 regions, the other 5 regions are linearly allocated, starting from
+// The mc, rw, ro, md and od regions are linearly allocated, starting from
// SharedBaseAddress, in the order of mc->rw->ro->md->od. The size of these 5 regions
// are page-aligned, and there's no gap between any consecutive regions.
//
// These 5 regions are populated in the following steps:
// [1] All classes are loaded in MetaspaceShared::preload_classes(). All metadata are
@@ -95,12 +103,12 @@
// [4] SymbolTable, StringTable, SystemDictionary, and a few other read-only data
// are copied into the ro region as read-only tables.
// [5] C++ vtables are copied into the md region.
// [6] Original class files are copied into the od region.
//
-// The s0/s1 regions are populated inside MetaspaceShared::dump_string_and_symbols. Their
-// layout is independent of the other 5 regions.
+// The s0/s1 and oa0/oa1 regions are populated inside MetaspaceShared::dump_java_heap_objects.
+// Their layout is independent of the other 5 regions.
class DumpRegion {
private:
const char* _name;
char* _base;
@@ -193,11 +201,11 @@
return base() <= p && p < top();
}
};
DumpRegion _mc_region("mc"), _ro_region("ro"), _rw_region("rw"), _md_region("md"), _od_region("od");
-DumpRegion _s0_region("s0"), _s1_region("s1");
+DumpRegion _s0_region("s0"), _s1_region("s1"), _oa0_region("oa0"), _oa1_region("oa1");
char* MetaspaceShared::misc_code_space_alloc(size_t num_bytes) {
return _mc_region.allocate(num_bytes);
}
@@ -854,12 +862,14 @@
// Populate the shared space.
class VM_PopulateDumpSharedSpace: public VM_Operation {
private:
GrowableArray<MemRegion> *_string_regions;
+ GrowableArray<MemRegion> *_open_archive_heap_regions;
- void dump_string_and_symbols();
+ void dump_java_heap_objects() NOT_CDS_JAVA_HEAP_RETURN;
+ void dump_symbols();
char* dump_read_only_tables();
void print_region_stats();
public:
VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
@@ -1070,13 +1080,12 @@
// cleanup
_ssc = NULL;
}
// We must relocate the System::_well_known_klasses only after we have copied the
- // strings in during dump_string_and_symbols(): during the string copy, we operate on old
- // String objects which assert that their klass is the old
- // SystemDictionary::String_klass().
+ // java objects in during dump_java_heap_objects(): during the object copy, we operate on
+ // old objects which assert that their klass is the original klass.
static void relocate_well_known_klasses() {
{
tty->print_cr("Relocating SystemDictionary::_well_known_klasses[] ... ");
ResourceMark rm;
RefRelocator ext_reloc;
@@ -1125,20 +1134,15 @@
void VM_PopulateDumpSharedSpace::write_region(FileMapInfo* mapinfo, int region_idx,
DumpRegion* dump_region, bool read_only, bool allow_exec) {
mapinfo->write_region(region_idx, dump_region->base(), dump_region->used(), read_only, allow_exec);
}
-void VM_PopulateDumpSharedSpace::dump_string_and_symbols() {
- tty->print_cr("Dumping string and symbol tables ...");
+void VM_PopulateDumpSharedSpace::dump_symbols() {
+ tty->print_cr("Dumping symbol table ...");
NOT_PRODUCT(SymbolTable::verify());
- NOT_PRODUCT(StringTable::verify());
SymbolTable::write_to_archive();
-
- // The string space has maximum two regions. See FileMapInfo::write_string_regions() for details.
- _string_regions = new GrowableArray<MemRegion>(2);
- StringTable::write_to_archive(_string_regions);
}
char* VM_PopulateDumpSharedSpace::dump_read_only_tables() {
char* oldtop = _ro_region.top();
// Reorder the system dictionary. Moving the symbols affects
@@ -1204,11 +1208,10 @@
tty->print_cr(" instance classes = %5d", num_inst);
tty->print_cr(" obj array classes = %5d", num_obj_array);
tty->print_cr(" type array classes = %5d", num_type_array);
}
-
// Ensure the ConstMethods won't be modified at run-time
tty->print("Updating ConstMethods ... ");
rewrite_nofast_bytecodes_and_calculate_fingerprints();
tty->print_cr("done. ");
@@ -1218,11 +1221,17 @@
tty->print_cr("done. ");
ArchiveCompactor::initialize();
ArchiveCompactor::copy_and_compact();
- dump_string_and_symbols();
+ dump_symbols();
+
+ // Dump supported java heap objects
+ _string_regions = NULL;
+ _open_archive_heap_regions = NULL;
+ dump_java_heap_objects();
+
ArchiveCompactor::relocate_well_known_klasses();
char* read_only_tables_start = dump_read_only_tables();
_ro_region.pack(&_md_region);
@@ -1256,12 +1265,14 @@
mapinfo->set_misc_data_patching_start(vtbl_list);
mapinfo->set_cds_i2i_entry_code_buffers(MetaspaceShared::cds_i2i_entry_code_buffers());
mapinfo->set_cds_i2i_entry_code_buffers_size(MetaspaceShared::cds_i2i_entry_code_buffers_size());
mapinfo->set_core_spaces_size(core_spaces_size);
- char* s0_start, *s0_top, *s0_end;
- char* s1_start, *s1_top, *s1_end;
+ char* s0_start, *s0_top;
+ char* s1_start, *s1_top;
+ char* oa0_start, *oa0_top;
+ char* oa1_start, *oa1_top;
for (int pass=1; pass<=2; pass++) {
if (pass == 1) {
// The first pass doesn't actually write the data to disk. All it
// does is to update the fields in the mapinfo->_header.
@@ -1280,22 +1291,31 @@
write_region(mapinfo, MetaspaceShared::rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
write_region(mapinfo, MetaspaceShared::md, &_md_region, /*read_only=*/false,/*allow_exec=*/false);
write_region(mapinfo, MetaspaceShared::od, &_od_region, /*read_only=*/true, /*allow_exec=*/false);
- mapinfo->write_string_regions(_string_regions,
- &s0_start, &s0_top, &s0_end,
- &s1_start, &s1_top, &s1_end);
+ mapinfo->write_archive_heap_regions(_string_regions,
+ MetaspaceShared::first_string,
+ MetaspaceShared::max_strings,
+ &s0_start, &s0_top,
+ &s1_start, &s1_top);
+ mapinfo->write_archive_heap_regions(_open_archive_heap_regions,
+ MetaspaceShared::first_open_archive_heap_region,
+ MetaspaceShared::max_open_archive_heap_region,
+ &oa0_start, &oa0_top,
+ &oa1_start, &oa1_top);
}
mapinfo->close();
// Restore the vtable in case we invoke any virtual methods.
MetaspaceShared::clone_cpp_vtables((intptr_t*)vtbl_list);
- _s0_region.init(s0_start, s0_top, s0_end);
- _s1_region.init(s1_start, s1_top, s1_end);
+ _s0_region.init(s0_start, s0_top, s0_top);
+ _s1_region.init(s1_start, s1_top, s1_top);
+ _oa0_region.init(oa0_start, oa0_top, oa0_top);
+ _oa1_region.init(oa1_start, oa1_top, oa1_top);
print_region_stats();
if (log_is_enabled(Info, cds)) {
ArchiveCompactor::alloc_stats()->print_stats(int(_ro_region.used()), int(_rw_region.used()),
int(_mc_region.used()), int(_md_region.used()));
@@ -1305,24 +1325,28 @@
void VM_PopulateDumpSharedSpace::print_region_stats() {
// Print statistics of all the regions
const size_t total_reserved = _ro_region.reserved() + _rw_region.reserved() +
_mc_region.reserved() + _md_region.reserved() +
_od_region.reserved() +
- _s0_region.reserved() + _s1_region.reserved();
+ _s0_region.reserved() + _s1_region.reserved() +
+ _oa0_region.reserved() + _oa1_region.reserved();
const size_t total_bytes = _ro_region.used() + _rw_region.used() +
_mc_region.used() + _md_region.used() +
_od_region.used() +
- _s0_region.used() + _s1_region.used();
+ _s0_region.used() + _s1_region.used() +
+ _oa0_region.used() + _oa1_region.used();
const double total_u_perc = total_bytes / double(total_reserved) * 100.0;
_mc_region.print(total_reserved);
_rw_region.print(total_reserved);
_ro_region.print(total_reserved);
_md_region.print(total_reserved);
_od_region.print(total_reserved);
_s0_region.print(total_reserved);
_s1_region.print(total_reserved);
+ _oa0_region.print(total_reserved);
+ _oa1_region.print(total_reserved);
tty->print_cr("total : " SIZE_FORMAT_W(9) " [100.0%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used]",
total_bytes, total_reserved, total_u_perc);
}
@@ -1350,10 +1374,12 @@
// Link the class to cause the bytecodes to be rewritten and the
// cpcache to be created. Class verification is done according
// to -Xverify setting.
_made_progress |= MetaspaceShared::try_link_class(ik, THREAD);
guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class");
+
+ ik->constants()->resolve_class_constants(THREAD);
}
}
};
class CheckSharedClassesClosure : public KlassClosure {
@@ -1554,10 +1580,98 @@
} else {
return false;
}
}
+#if INCLUDE_CDS_JAVA_HEAP
+void VM_PopulateDumpSharedSpace::dump_java_heap_objects() {
+ if (!MetaspaceShared::allow_archive_heap_object()) {
+ if (log_is_enabled(Info, cds)) {
+ log_info(cds)(
+ "Archived java heap is not supported as UseG1GC, "
+ "UseCompressedOops and UseCompressedClassPointers are required."
+ "Current settings: UseG1GC=%s, UseCompressedOops=%s, UseCompressedClassPointers=%s.",
+ BOOL_TO_STR(UseG1GC), BOOL_TO_STR(UseCompressedOops),
+ BOOL_TO_STR(UseCompressedClassPointers));
+ }
+ return;
+ }
+
+ // Cache for recording where the archived objects are copied to
+ MetaspaceShared::create_archive_object_cache();
+
+ tty->print_cr("Dumping String objects to closed archive heap region ...");
+ NOT_PRODUCT(StringTable::verify());
+ // The string space has maximum two regions. See FileMapInfo::write_string_regions() for details.
+ _string_regions = new GrowableArray<MemRegion>(2);
+ StringTable::write_to_archive(_string_regions);
+
+ tty->print_cr("Dumping objects to open archive heap region ...");
+ _open_archive_heap_regions = new GrowableArray<MemRegion>(2);
+ MetaspaceShared::dump_open_archive_heap_objects(_open_archive_heap_regions);
+}
+
+void MetaspaceShared::dump_open_archive_heap_objects(
+ GrowableArray<MemRegion> * open_archive) {
+ assert(UseG1GC, "Only support G1 GC");
+ assert(UseCompressedOops && UseCompressedClassPointers,
+ "Only support UseCompressedOops and UseCompressedClassPointers enabled");
+
+ Thread* THREAD = Thread::current();
+ G1CollectedHeap::heap()->begin_archive_alloc_range(true /* open */);
+
+ MetaspaceShared::archive_resolved_constants(THREAD);
+
+ G1CollectedHeap::heap()->end_archive_alloc_range(open_archive,
+ os::vm_allocation_granularity());
+}
+
+MetaspaceShared::ArchivedObjectCache* MetaspaceShared::_archive_object_cache = NULL;
+oop MetaspaceShared::archive_heap_object(oop obj, Thread* THREAD) {
+ assert(DumpSharedSpaces, "dump-time only");
+
+ NoSafepointVerifier nsv;
+
+ ArchivedObjectCache* cache = MetaspaceShared::archive_object_cache();
+ oop* p = cache->get(obj);
+ if (p != NULL) {
+ // already archived
+ return *p;
+ }
+
+ int len = obj->size();
+ if (G1CollectedHeap::heap()->is_archive_alloc_too_large(len)) {
+ return NULL;
+ }
+
+ int hash = obj->identity_hash();
+ oop archived_oop = (oop)G1CollectedHeap::heap()->archive_mem_allocate(len);
+ if (archived_oop != NULL) {
+ Copy::aligned_disjoint_words((HeapWord*)obj, (HeapWord*)archived_oop, len);
+ relocate_klass_ptr(archived_oop);
+ cache->put(obj, archived_oop);
+ }
+ return archived_oop;
+}
+
+void MetaspaceShared::archive_resolved_constants(Thread* THREAD) {
+ int i;
+ for (i = 0; i < _global_klass_objects->length(); i++) {
+ Klass* k = _global_klass_objects->at(i);
+ if (k->is_instance_klass()) {
+ InstanceKlass* ik = InstanceKlass::cast(k);
+ ik->constants()->archive_resolved_references(THREAD);
+ }
+ }
+}
+
+void MetaspaceShared::fixup_mapped_heap_regions() {
+ FileMapInfo *mapinfo = FileMapInfo::current_info();
+ mapinfo->fixup_mapped_heap_regions();
+}
+#endif // INCLUDE_CDS_JAVA_HEAP
+
// Closure for serializing initialization data in from a data area
// (ptr_array) read from the shared file.
class ReadClosure : public SerializeClosure {
private:
@@ -1741,15 +1855,10 @@
vm_exit(0);
}
}
}
-void MetaspaceShared::fixup_shared_string_regions() {
- FileMapInfo *mapinfo = FileMapInfo::current_info();
- mapinfo->fixup_string_regions();
-}
-
// JVM/TI RedefineClasses() support:
bool MetaspaceShared::remap_shared_readonly_as_readwrite() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
if (UseSharedSpaces) {
< prev index next >