15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "cds/aotClassLinker.hpp"
27 #include "cds/aotLinkedClassBulkLoader.hpp"
28 #include "cds/archiveBuilder.hpp"
29 #include "cds/archiveHeapWriter.hpp"
30 #include "cds/archiveUtils.hpp"
31 #include "cds/cdsConfig.hpp"
32 #include "cds/cppVtables.hpp"
33 #include "cds/dumpAllocStats.hpp"
34 #include "cds/dynamicArchive.hpp"
35 #include "cds/heapShared.hpp"
36 #include "cds/metaspaceShared.hpp"
37 #include "cds/regeneratedClasses.hpp"
38 #include "classfile/classLoader.hpp"
39 #include "classfile/classLoaderDataShared.hpp"
40 #include "classfile/classLoaderExt.hpp"
41 #include "classfile/javaClasses.hpp"
42 #include "classfile/symbolTable.hpp"
43 #include "classfile/systemDictionaryShared.hpp"
44 #include "classfile/vmClasses.hpp"
45 #include "interpreter/abstractInterpreter.hpp"
46 #include "jvm.h"
47 #include "logging/log.hpp"
48 #include "logging/logStream.hpp"
49 #include "memory/allStatic.hpp"
50 #include "memory/memRegion.hpp"
51 #include "memory/resourceArea.hpp"
52 #include "oops/compressedKlass.inline.hpp"
53 #include "oops/instanceKlass.hpp"
54 #include "oops/objArrayKlass.hpp"
55 #include "oops/objArrayOop.inline.hpp"
56 #include "oops/oopHandle.inline.hpp"
57 #include "runtime/arguments.hpp"
58 #include "runtime/fieldDescriptor.inline.hpp"
59 #include "runtime/globals_extension.hpp"
60 #include "runtime/javaThread.hpp"
61 #include "runtime/sharedRuntime.hpp"
62 #include "utilities/align.hpp"
63 #include "utilities/bitMap.inline.hpp"
64 #include "utilities/formatBuffer.hpp"
65
66 ArchiveBuilder* ArchiveBuilder::_current = nullptr;
67
68 ArchiveBuilder::OtherROAllocMark::~OtherROAllocMark() {
69 char* newtop = ArchiveBuilder::current()->_ro_region.top();
70 ArchiveBuilder::alloc_stats()->record_other_type(int(newtop - _oldtop), true);
71 }
72
73 ArchiveBuilder::SourceObjList::SourceObjList() : _ptrmap(16 * K, mtClassShared) {
74 _total_bytes = 0;
75 _objs = new (mtClassShared) GrowableArray<SourceObjInfo*>(128 * K, mtClassShared);
76 }
147
148 RelocateEmbeddedPointers relocator(builder, src_info->buffered_addr(), start);
149 _ptrmap.iterate(&relocator, start, end);
150 }
151
152 ArchiveBuilder::ArchiveBuilder() :
153 _current_dump_region(nullptr),
154 _buffer_bottom(nullptr),
155 _last_verified_top(nullptr),
156 _num_dump_regions_used(0),
157 _other_region_used_bytes(0),
158 _requested_static_archive_bottom(nullptr),
159 _requested_static_archive_top(nullptr),
160 _requested_dynamic_archive_bottom(nullptr),
161 _requested_dynamic_archive_top(nullptr),
162 _mapped_static_archive_bottom(nullptr),
163 _mapped_static_archive_top(nullptr),
164 _buffer_to_requested_delta(0),
165 _rw_region("rw", MAX_SHARED_DELTA),
166 _ro_region("ro", MAX_SHARED_DELTA),
167 _ptrmap(mtClassShared),
168 _rw_ptrmap(mtClassShared),
169 _ro_ptrmap(mtClassShared),
170 _rw_src_objs(),
171 _ro_src_objs(),
172 _src_obj_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
173 _buffered_to_src_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
174 _total_heap_region_size(0),
175 _estimated_metaspaceobj_bytes(0),
176 _estimated_hashtable_bytes(0)
177 {
178 _klasses = new (mtClassShared) GrowableArray<Klass*>(4 * K, mtClassShared);
179 _symbols = new (mtClassShared) GrowableArray<Symbol*>(256 * K, mtClassShared);
180 _entropy_seed = 0x12345678;
181 assert(_current == nullptr, "must be");
182 _current = this;
183 }
184
185 ArchiveBuilder::~ArchiveBuilder() {
186 assert(_current == this, "must be");
187 _current = nullptr;
188
189 for (int i = 0; i < _symbols->length(); i++) {
301 return -1;
302 } else {
303 assert(a[0] > b[0], "Duplicated symbol %s unexpected", (*a)->as_C_string());
304 return 1;
305 }
306 }
307
308 int ArchiveBuilder::compare_klass_by_name(Klass** a, Klass** b) {
309 return a[0]->name()->fast_compare(b[0]->name());
310 }
311
312 void ArchiveBuilder::sort_klasses() {
313 log_info(cds)("Sorting classes ... ");
314 _klasses->sort(compare_klass_by_name);
315 }
316
317 size_t ArchiveBuilder::estimate_archive_size() {
318 // size of the symbol table and two dictionaries, plus the RunTimeClassInfo's
319 size_t symbol_table_est = SymbolTable::estimate_size_for_archive();
320 size_t dictionary_est = SystemDictionaryShared::estimate_size_for_archive();
321 _estimated_hashtable_bytes = symbol_table_est + dictionary_est;
322
323 if (CDSConfig::is_dumping_aot_linked_classes()) {
324 // This is difficult to estimate when dumping the dynamic archive, as the
325 // AOTLinkedClassTable may need to contain classes in the static archive as well.
326 //
327 // Just give a generous estimate for now. We will remove estimate_archive_size()
328 // in JDK-8340416
329 _estimated_hashtable_bytes += 20 * 1024 * 1024;
330 }
331
332 size_t total = 0;
333
334 total += _estimated_metaspaceobj_bytes;
335 total += _estimated_hashtable_bytes;
336
337 // allow fragmentation at the end of each dump region
338 total += _total_dump_regions * MetaspaceShared::core_region_alignment();
339
340 log_info(cds)("_estimated_hashtable_bytes = " SIZE_FORMAT " + " SIZE_FORMAT " = " SIZE_FORMAT,
341 symbol_table_est, dictionary_est, _estimated_hashtable_bytes);
530 _rw_src_objs.remember_embedded_pointer(src_info, ref);
531 }
532 }
533 }
534
535 void ArchiveBuilder::gather_source_objs() {
536 ResourceMark rm;
537 log_info(cds)("Gathering all archivable objects ... ");
538 gather_klasses_and_symbols();
539 GatherSortedSourceObjs doit(this);
540 iterate_sorted_roots(&doit);
541 doit.finish();
542 }
543
544 bool ArchiveBuilder::is_excluded(Klass* klass) {
545 if (klass->is_instance_klass()) {
546 InstanceKlass* ik = InstanceKlass::cast(klass);
547 return SystemDictionaryShared::is_excluded_class(ik);
548 } else if (klass->is_objArray_klass()) {
549 Klass* bottom = ObjArrayKlass::cast(klass)->bottom_klass();
550 if (MetaspaceShared::is_shared_static(bottom)) {
551 // The bottom class is in the static archive so it's clearly not excluded.
552 assert(CDSConfig::is_dumping_dynamic_archive(), "sanity");
553 return false;
554 } else if (bottom->is_instance_klass()) {
555 return SystemDictionaryShared::is_excluded_class(InstanceKlass::cast(bottom));
556 }
557 }
558
559 return false;
560 }
561
562 ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref *ref) {
563 address obj = ref->obj();
564 if (MetaspaceShared::is_in_shared_metaspace(obj)) {
565 // Don't dump existing shared metadata again.
566 return point_to_it;
567 } else if (ref->msotype() == MetaspaceObj::MethodDataType ||
568 ref->msotype() == MetaspaceObj::MethodCountersType) {
569 return set_to_null;
570 } else {
571 if (ref->msotype() == MetaspaceObj::ClassType) {
572 Klass* klass = (Klass*)ref->obj();
573 assert(klass->is_klass(), "must be");
574 if (is_excluded(klass)) {
575 ResourceMark rm;
576 log_debug(cds, dynamic)("Skipping class (excluded): %s", klass->external_name());
577 return set_to_null;
578 }
579 }
580
581 return make_a_copy;
582 }
583 }
584
585 void ArchiveBuilder::start_dump_region(DumpRegion* next) {
586 address bottom = _last_verified_top;
587 address top = (address)(current_dump_region()->top());
588 _other_region_used_bytes += size_t(top - bottom);
589
761 }
762
763 bool ArchiveBuilder::has_been_buffered(address src_addr) const {
764 if (RegeneratedClasses::has_been_regenerated(src_addr) ||
765 _src_obj_table.get(src_addr) == nullptr ||
766 get_buffered_addr(src_addr) == nullptr) {
767 return false;
768 } else {
769 return true;
770 }
771 }
772
773 address ArchiveBuilder::get_buffered_addr(address src_addr) const {
774 SourceObjInfo* p = _src_obj_table.get(src_addr);
775 assert(p != nullptr, "src_addr " INTPTR_FORMAT " is used but has not been archived",
776 p2i(src_addr));
777
778 return p->buffered_addr();
779 }
780
781 address ArchiveBuilder::get_source_addr(address buffered_addr) const {
782 assert(is_in_buffer_space(buffered_addr), "must be");
783 address* src_p = _buffered_to_src_table.get(buffered_addr);
784 assert(src_p != nullptr && *src_p != nullptr, "must be");
785 return *src_p;
786 }
787
788 void ArchiveBuilder::relocate_embedded_pointers(ArchiveBuilder::SourceObjList* src_objs) {
789 for (int i = 0; i < src_objs->objs()->length(); i++) {
790 src_objs->relocate(i, this);
791 }
792 }
793
794 void ArchiveBuilder::relocate_metaspaceobj_embedded_pointers() {
795 log_info(cds)("Relocating embedded pointers in core regions ... ");
796 relocate_embedded_pointers(&_rw_src_objs);
797 relocate_embedded_pointers(&_ro_src_objs);
798 }
799
800 #define ADD_COUNT(x) \
974 log_info(cds)(" boot " STATS_FORMAT, STATS_PARAMS(boot_klasses));
975 log_info(cds)(" vm " STATS_FORMAT, STATS_PARAMS(vm_klasses));
976 log_info(cds)(" platform " STATS_FORMAT, STATS_PARAMS(platform_klasses));
977 log_info(cds)(" app " STATS_FORMAT, STATS_PARAMS(app_klasses));
978 log_info(cds)(" unregistered " STATS_FORMAT, STATS_PARAMS(unregistered_klasses));
979 log_info(cds)(" (enum) " STATS_FORMAT, STATS_PARAMS(enum_klasses));
980 log_info(cds)(" (hidden) " STATS_FORMAT, STATS_PARAMS(hidden_klasses));
981 log_info(cds)(" (old) " STATS_FORMAT, STATS_PARAMS(old_klasses));
982 log_info(cds)(" (unlinked) = %5d, boot = %d, plat = %d, app = %d, unreg = %d",
983 num_unlinked_klasses, boot_unlinked, platform_unlinked, app_unlinked, unreg_unlinked);
984 log_info(cds)(" obj array classes = %5d", num_obj_array_klasses);
985 log_info(cds)(" type array classes = %5d", num_type_array_klasses);
986 log_info(cds)(" symbols = %5d", _symbols->length());
987
988 #undef STATS_FORMAT
989 #undef STATS_PARAMS
990
991 DynamicArchive::make_array_klasses_shareable();
992 }
993
994 void ArchiveBuilder::serialize_dynamic_archivable_items(SerializeClosure* soc) {
995 SymbolTable::serialize_shared_table_header(soc, false);
996 SystemDictionaryShared::serialize_dictionary_headers(soc, false);
997 DynamicArchive::serialize_array_klasses(soc);
998 AOTLinkedClassBulkLoader::serialize(soc, false);
999 }
1000
1001 uintx ArchiveBuilder::buffer_to_offset(address p) const {
1002 address requested_p = to_requested(p);
1003 assert(requested_p >= _requested_static_archive_bottom, "must be");
1004 return requested_p - _requested_static_archive_bottom;
1005 }
1006
1007 uintx ArchiveBuilder::any_to_offset(address p) const {
1008 if (is_in_mapped_static_archive(p)) {
1009 assert(CDSConfig::is_dumping_dynamic_archive(), "must be");
1010 return p - _mapped_static_archive_bottom;
1011 }
1012 if (!is_in_buffer_space(p)) {
1013 // p must be a "source" address
1014 p = get_buffered_addr(p);
1015 }
1016 return buffer_to_offset(p);
1017 }
1018
1019 address ArchiveBuilder::offset_to_buffered_address(u4 offset) const {
1020 address requested_addr = _requested_static_archive_bottom + offset;
1021 address buffered_addr = requested_addr - _buffer_to_requested_delta;
1022 assert(is_in_buffer_space(buffered_addr), "bad offset");
1023 return buffered_addr;
1024 }
1025
1026 #if INCLUDE_CDS_JAVA_HEAP
1027 narrowKlass ArchiveBuilder::get_requested_narrow_klass(Klass* k) {
1028 assert(CDSConfig::is_dumping_heap(), "sanity");
1029 k = get_buffered_klass(k);
1030 Klass* requested_k = to_requested(k);
1031 const int narrow_klass_shift = ArchiveBuilder::precomputed_narrow_klass_shift();
1032 #ifdef ASSERT
1033 const size_t klass_alignment = MAX2(SharedSpaceObjectAlignment, (size_t)nth_bit(narrow_klass_shift));
1034 assert(is_aligned(k, klass_alignment), "Klass " PTR_FORMAT " misaligned.", p2i(k));
1035 #endif
1036 address narrow_klass_base = _requested_static_archive_bottom; // runtime encoding base == runtime mapping start
1037 // Note: use the "raw" version of encode that takes explicit narrow klass base and shift. Don't use any
1038 // of the variants that do sanity checks, nor any of those that use the current - dump - JVM's encoding setting.
1115 ArchivePtrMarker::compact(_max_non_null_offset);
1116 }
1117 };
1118
1119 #ifdef _LP64
1120 int ArchiveBuilder::precomputed_narrow_klass_shift() {
1121 // Legacy Mode:
1122 // We use 32 bits for narrowKlass, which should cover the full 4G Klass range. Shift can be 0.
1123 // CompactObjectHeader Mode:
1124 // narrowKlass is much smaller, and we use the highest possible shift value to later get the maximum
1125 // Klass encoding range.
1126 //
1127 // Note that all of this may change in the future, if we decide to correct the pre-calculated
1128 // narrow Klass IDs at archive load time.
1129 assert(UseCompressedClassPointers, "Only needed for compressed class pointers");
1130 return UseCompactObjectHeaders ? CompressedKlassPointers::max_shift() : 0;
1131 }
1132 #endif // _LP64
1133
1134 void ArchiveBuilder::relocate_to_requested() {
1135 ro_region()->pack();
1136
1137 size_t my_archive_size = buffer_top() - buffer_bottom();
1138
1139 if (CDSConfig::is_dumping_static_archive()) {
1140 _requested_static_archive_top = _requested_static_archive_bottom + my_archive_size;
1141 RelocateBufferToRequested<true> patcher(this);
1142 patcher.doit();
1143 } else {
1144 assert(CDSConfig::is_dumping_dynamic_archive(), "must be");
1145 _requested_dynamic_archive_top = _requested_dynamic_archive_bottom + my_archive_size;
1146 RelocateBufferToRequested<false> patcher(this);
1147 patcher.doit();
1148 }
1149 }
1150
1151 // Write detailed info to a mapfile to analyze contents of the archive.
1152 // static dump:
1153 // java -Xshare:dump -Xlog:cds+map=trace:file=cds.map:none:filesize=0
1154 // dynamic dump:
1155 // java -cp MyApp.jar -XX:ArchiveClassesAtExit=MyApp.jsa \
1377 ArchiveBuilder* builder = ArchiveBuilder::current();
1378 Klass* requested_klass = builder->to_requested(builder->get_buffered_addr(source_klass));
1379
1380 st.print(" - klass: ");
1381 source_klass->print_value_on(&st);
1382 st.print(" " PTR_FORMAT, p2i(requested_klass));
1383 st.cr();
1384
1385 if (source_oop->is_typeArray()) {
1386 TypeArrayKlass::cast(source_klass)->oop_print_elements_on(typeArrayOop(source_oop), &st);
1387 } else if (source_oop->is_objArray()) {
1388 objArrayOop source_obj_array = objArrayOop(source_oop);
1389 for (int i = 0; i < source_obj_array->length(); i++) {
1390 st.print(" -%4d: ", i);
1391 print_oop_with_requested_addr_cr(&st, source_obj_array->obj_at(i));
1392 }
1393 } else {
1394 st.print_cr(" - fields (" SIZE_FORMAT " words):", source_oop->size());
1395 ArchivedFieldPrinter print_field(heap_info, &st, source_oop, buffered_addr);
1396 InstanceKlass::cast(source_klass)->print_nonstatic_fields(&print_field);
1397 }
1398 }
1399 }
1400
1401 static void log_heap_roots() {
1402 LogStreamHandle(Trace, cds, map, oops) st;
1403 if (st.is_enabled()) {
1404 for (int i = 0; i < HeapShared::pending_roots()->length(); i++) {
1405 st.print("roots[%4d]: ", i);
1406 print_oop_with_requested_addr_cr(&st, HeapShared::pending_roots()->at(i));
1407 }
1408 }
1409 }
1410
1411 // The output looks like this. The first number is the requested address. The second number is
1412 // the narrowOop version of the requested address.
1413 // 0x00000007ffc7e840 (0xfff8fd08) java.lang.Class
1414 // 0x00000007ffc000f8 (0xfff8001f) [B length: 11
1415 static void print_oop_with_requested_addr_cr(outputStream* st, oop source_oop, bool print_addr = true) {
1416 if (source_oop == nullptr) {
1417 st->print_cr("null");
1418 } else {
1419 ResourceMark rm;
1420 oop requested_obj = ArchiveHeapWriter::source_obj_to_requested_obj(source_oop);
1421 if (print_addr) {
1422 st->print(PTR_FORMAT " ", p2i(requested_obj));
1423 }
1424 if (UseCompressedOops) {
1425 st->print("(0x%08x) ", CompressedOops::narrow_oop_value(requested_obj));
1426 }
1427 if (source_oop->is_array()) {
1428 int array_len = arrayOop(source_oop)->length();
1429 st->print_cr("%s length: %d", source_oop->klass()->external_name(), array_len);
1430 } else {
1431 st->print_cr("%s", source_oop->klass()->external_name());
1432 }
1433 }
1434 }
1435 #endif // INCLUDE_CDS_JAVA_HEAP
1436
1437 // Log all the data [base...top). Pretend that the base address
1438 // will be mapped to requested_base at run-time.
1439 static void log_as_hex(address base, address top, address requested_base, bool is_heap = false) {
1440 assert(top >= base, "must be");
1441
1442 LogStreamHandle(Trace, cds, map) lsh;
1443 if (lsh.is_enabled()) {
1444 int unitsize = sizeof(address);
1445 if (is_heap && UseCompressedOops) {
1446 // This makes the compressed oop pointers easier to read, but
1447 // longs and doubles will be split into two words.
1448 unitsize = sizeof(narrowOop);
1449 }
1450 os::print_hex_dump(&lsh, base, top, unitsize, /* print_ascii=*/true, /* bytes_per_line=*/32, requested_base);
1451 }
1484 if (heap_info->is_used()) {
1485 log_heap_region(heap_info);
1486 }
1487 #endif
1488
1489 log_info(cds, map)("[End of CDS archive map]");
1490 }
1491 }; // end ArchiveBuilder::CDSMapLogger
1492
1493 void ArchiveBuilder::print_stats() {
1494 _alloc_stats.print_stats(int(_ro_region.used()), int(_rw_region.used()));
1495 }
1496
1497 void ArchiveBuilder::write_archive(FileMapInfo* mapinfo, ArchiveHeapInfo* heap_info) {
1498 // Make sure NUM_CDS_REGIONS (exported in cds.h) agrees with
1499 // MetaspaceShared::n_regions (internal to hotspot).
1500 assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity");
1501
1502 write_region(mapinfo, MetaspaceShared::rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
1503 write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
1504
1505 // Split pointer map into read-write and read-only bitmaps
1506 ArchivePtrMarker::initialize_rw_ro_maps(&_rw_ptrmap, &_ro_ptrmap);
1507
1508 size_t bitmap_size_in_bytes;
1509 char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::rw_ptrmap(), ArchivePtrMarker::ro_ptrmap(), heap_info,
1510 bitmap_size_in_bytes);
1511
1512 if (heap_info->is_used()) {
1513 _total_heap_region_size = mapinfo->write_heap_region(heap_info);
1514 }
1515
1516 print_region_stats(mapinfo, heap_info);
1517
1518 mapinfo->set_requested_base((char*)MetaspaceShared::requested_base_address());
1519 mapinfo->set_header_crc(mapinfo->compute_header_crc());
1520 // After this point, we should not write any data into mapinfo->header() since this
1521 // would corrupt its checksum we have calculated before.
1522 mapinfo->write_header();
1523 mapinfo->close();
1524
1525 if (log_is_enabled(Info, cds)) {
1526 print_stats();
1527 }
1528
1529 if (log_is_enabled(Info, cds, map)) {
1535 }
1536
1537 void ArchiveBuilder::write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only, bool allow_exec) {
1538 mapinfo->write_region(region_idx, dump_region->base(), dump_region->used(), read_only, allow_exec);
1539 }
1540
1541 void ArchiveBuilder::print_region_stats(FileMapInfo *mapinfo, ArchiveHeapInfo* heap_info) {
1542 // Print statistics of all the regions
1543 const size_t bitmap_used = mapinfo->region_at(MetaspaceShared::bm)->used();
1544 const size_t bitmap_reserved = mapinfo->region_at(MetaspaceShared::bm)->used_aligned();
1545 const size_t total_reserved = _ro_region.reserved() + _rw_region.reserved() +
1546 bitmap_reserved +
1547 _total_heap_region_size;
1548 const size_t total_bytes = _ro_region.used() + _rw_region.used() +
1549 bitmap_used +
1550 _total_heap_region_size;
1551 const double total_u_perc = percent_of(total_bytes, total_reserved);
1552
1553 _rw_region.print(total_reserved);
1554 _ro_region.print(total_reserved);
1555
1556 print_bitmap_region_stats(bitmap_used, total_reserved);
1557
1558 if (heap_info->is_used()) {
1559 print_heap_region_stats(heap_info, total_reserved);
1560 }
1561
1562 log_debug(cds)("total : " SIZE_FORMAT_W(9) " [100.0%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used]",
1563 total_bytes, total_reserved, total_u_perc);
1564 }
1565
1566 void ArchiveBuilder::print_bitmap_region_stats(size_t size, size_t total_size) {
1567 log_debug(cds)("bm space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [100.0%% used]",
1568 size, size/double(total_size)*100.0, size);
1569 }
1570
1571 void ArchiveBuilder::print_heap_region_stats(ArchiveHeapInfo *info, size_t total_size) {
1572 char* start = info->buffer_start();
1573 size_t size = info->buffer_byte_size();
1574 char* top = start + size;
|
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "cds/aotClassLinker.hpp"
27 #include "cds/aotLinkedClassBulkLoader.hpp"
28 #include "cds/archiveBuilder.hpp"
29 #include "cds/archiveHeapWriter.hpp"
30 #include "cds/archiveUtils.hpp"
31 #include "cds/cdsConfig.hpp"
32 #include "cds/cppVtables.hpp"
33 #include "cds/dumpAllocStats.hpp"
34 #include "cds/dynamicArchive.hpp"
35 #include "cds/finalImageRecipes.hpp"
36 #include "cds/heapShared.hpp"
37 #include "cds/metaspaceShared.hpp"
38 #include "cds/regeneratedClasses.hpp"
39 #include "classfile/classLoader.hpp"
40 #include "classfile/classLoaderDataShared.hpp"
41 #include "classfile/classLoaderExt.hpp"
42 #include "classfile/javaClasses.hpp"
43 #include "classfile/symbolTable.hpp"
44 #include "classfile/systemDictionaryShared.hpp"
45 #include "classfile/vmClasses.hpp"
46 #include "interpreter/abstractInterpreter.hpp"
47 #include "jvm.h"
48 #include "logging/log.hpp"
49 #include "logging/logStream.hpp"
50 #include "memory/allStatic.hpp"
51 #include "memory/memRegion.hpp"
52 #include "memory/resourceArea.hpp"
53 #include "oops/compressedKlass.inline.hpp"
54 #include "oops/instanceKlass.hpp"
55 #include "oops/methodCounters.hpp"
56 #include "oops/methodData.hpp"
57 #include "oops/objArrayKlass.hpp"
58 #include "oops/objArrayOop.inline.hpp"
59 #include "oops/oopHandle.inline.hpp"
60 #include "oops/trainingData.hpp"
61 #include "runtime/arguments.hpp"
62 #include "runtime/fieldDescriptor.inline.hpp"
63 #include "runtime/globals_extension.hpp"
64 #include "runtime/javaThread.hpp"
65 #include "runtime/sharedRuntime.hpp"
66 #include "utilities/align.hpp"
67 #include "utilities/bitMap.inline.hpp"
68 #include "utilities/formatBuffer.hpp"
69
70 ArchiveBuilder* ArchiveBuilder::_current = nullptr;
71
72 ArchiveBuilder::OtherROAllocMark::~OtherROAllocMark() {
73 char* newtop = ArchiveBuilder::current()->_ro_region.top();
74 ArchiveBuilder::alloc_stats()->record_other_type(int(newtop - _oldtop), true);
75 }
76
77 ArchiveBuilder::SourceObjList::SourceObjList() : _ptrmap(16 * K, mtClassShared) {
78 _total_bytes = 0;
79 _objs = new (mtClassShared) GrowableArray<SourceObjInfo*>(128 * K, mtClassShared);
80 }
151
152 RelocateEmbeddedPointers relocator(builder, src_info->buffered_addr(), start);
153 _ptrmap.iterate(&relocator, start, end);
154 }
155
156 ArchiveBuilder::ArchiveBuilder() :
157 _current_dump_region(nullptr),
158 _buffer_bottom(nullptr),
159 _last_verified_top(nullptr),
160 _num_dump_regions_used(0),
161 _other_region_used_bytes(0),
162 _requested_static_archive_bottom(nullptr),
163 _requested_static_archive_top(nullptr),
164 _requested_dynamic_archive_bottom(nullptr),
165 _requested_dynamic_archive_top(nullptr),
166 _mapped_static_archive_bottom(nullptr),
167 _mapped_static_archive_top(nullptr),
168 _buffer_to_requested_delta(0),
169 _rw_region("rw", MAX_SHARED_DELTA),
170 _ro_region("ro", MAX_SHARED_DELTA),
171 _cc_region("cc", MAX_SHARED_DELTA),
172 _ptrmap(mtClassShared),
173 _rw_ptrmap(mtClassShared),
174 _ro_ptrmap(mtClassShared),
175 _cc_ptrmap(mtClassShared),
176 _rw_src_objs(),
177 _ro_src_objs(),
178 _src_obj_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
179 _buffered_to_src_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
180 _total_heap_region_size(0),
181 _estimated_metaspaceobj_bytes(0),
182 _estimated_hashtable_bytes(0)
183 {
184 _klasses = new (mtClassShared) GrowableArray<Klass*>(4 * K, mtClassShared);
185 _symbols = new (mtClassShared) GrowableArray<Symbol*>(256 * K, mtClassShared);
186 _entropy_seed = 0x12345678;
187 assert(_current == nullptr, "must be");
188 _current = this;
189 }
190
191 ArchiveBuilder::~ArchiveBuilder() {
192 assert(_current == this, "must be");
193 _current = nullptr;
194
195 for (int i = 0; i < _symbols->length(); i++) {
307 return -1;
308 } else {
309 assert(a[0] > b[0], "Duplicated symbol %s unexpected", (*a)->as_C_string());
310 return 1;
311 }
312 }
313
314 int ArchiveBuilder::compare_klass_by_name(Klass** a, Klass** b) {
315 return a[0]->name()->fast_compare(b[0]->name());
316 }
317
318 void ArchiveBuilder::sort_klasses() {
319 log_info(cds)("Sorting classes ... ");
320 _klasses->sort(compare_klass_by_name);
321 }
322
323 size_t ArchiveBuilder::estimate_archive_size() {
324 // size of the symbol table and two dictionaries, plus the RunTimeClassInfo's
325 size_t symbol_table_est = SymbolTable::estimate_size_for_archive();
326 size_t dictionary_est = SystemDictionaryShared::estimate_size_for_archive();
327 size_t training_data_est = TrainingData::estimate_size_for_archive();
328 _estimated_hashtable_bytes = symbol_table_est + dictionary_est + training_data_est;
329
330 if (CDSConfig::is_dumping_final_static_archive()) {
331 _estimated_hashtable_bytes += 200 * 1024 * 1024; // FIXME -- need to iterate archived symbols??
332 }
333
334 if (CDSConfig::is_dumping_dynamic_archive()) {
335 // Some extra space for traning data. Be generous. Unused areas will be trimmed from the archive file.
336 _estimated_hashtable_bytes += 200 * 1024 * 1024;
337 }
338
339 if (CDSConfig::is_dumping_aot_linked_classes()) {
340 // This is difficult to estimate when dumping the dynamic archive, as the
341 // AOTLinkedClassTable may need to contain classes in the static archive as well.
342 //
343 // Just give a generous estimate for now. We will remove estimate_archive_size()
344 // in JDK-8340416
345 _estimated_hashtable_bytes += 20 * 1024 * 1024;
346 }
347
348 size_t total = 0;
349
350 total += _estimated_metaspaceobj_bytes;
351 total += _estimated_hashtable_bytes;
352
353 // allow fragmentation at the end of each dump region
354 total += _total_dump_regions * MetaspaceShared::core_region_alignment();
355
356 log_info(cds)("_estimated_hashtable_bytes = " SIZE_FORMAT " + " SIZE_FORMAT " = " SIZE_FORMAT,
357 symbol_table_est, dictionary_est, _estimated_hashtable_bytes);
546 _rw_src_objs.remember_embedded_pointer(src_info, ref);
547 }
548 }
549 }
550
551 void ArchiveBuilder::gather_source_objs() {
552 ResourceMark rm;
553 log_info(cds)("Gathering all archivable objects ... ");
554 gather_klasses_and_symbols();
555 GatherSortedSourceObjs doit(this);
556 iterate_sorted_roots(&doit);
557 doit.finish();
558 }
559
560 bool ArchiveBuilder::is_excluded(Klass* klass) {
561 if (klass->is_instance_klass()) {
562 InstanceKlass* ik = InstanceKlass::cast(klass);
563 return SystemDictionaryShared::is_excluded_class(ik);
564 } else if (klass->is_objArray_klass()) {
565 Klass* bottom = ObjArrayKlass::cast(klass)->bottom_klass();
566 if (CDSConfig::is_dumping_dynamic_archive() && MetaspaceShared::is_shared_static(bottom)) {
567 // The bottom class is in the static archive so it's clearly not excluded.
568 assert(CDSConfig::is_dumping_dynamic_archive(), "sanity");
569 return false;
570 } else if (bottom->is_instance_klass()) {
571 return SystemDictionaryShared::is_excluded_class(InstanceKlass::cast(bottom));
572 }
573 }
574
575 return false;
576 }
577
578 ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref *ref) {
579 address obj = ref->obj();
580 if (CDSConfig::is_dumping_dynamic_archive() && MetaspaceShared::is_in_shared_metaspace(obj)) {
581 // Don't dump existing shared metadata again.
582 return point_to_it;
583 } else if (ref->msotype() == MetaspaceObj::MethodDataType ||
584 ref->msotype() == MetaspaceObj::MethodCountersType ||
585 ref->msotype() == MetaspaceObj::KlassTrainingDataType ||
586 ref->msotype() == MetaspaceObj::MethodTrainingDataType ||
587 ref->msotype() == MetaspaceObj::CompileTrainingDataType) {
588 return TrainingData::need_data() ? make_a_copy : set_to_null;
589 } else {
590 if (ref->msotype() == MetaspaceObj::ClassType) {
591 Klass* klass = (Klass*)ref->obj();
592 assert(klass->is_klass(), "must be");
593 if (is_excluded(klass)) {
594 ResourceMark rm;
595 log_debug(cds, dynamic)("Skipping class (excluded): %s", klass->external_name());
596 return set_to_null;
597 }
598 }
599
600 return make_a_copy;
601 }
602 }
603
604 void ArchiveBuilder::start_dump_region(DumpRegion* next) {
605 address bottom = _last_verified_top;
606 address top = (address)(current_dump_region()->top());
607 _other_region_used_bytes += size_t(top - bottom);
608
780 }
781
782 bool ArchiveBuilder::has_been_buffered(address src_addr) const {
783 if (RegeneratedClasses::has_been_regenerated(src_addr) ||
784 _src_obj_table.get(src_addr) == nullptr ||
785 get_buffered_addr(src_addr) == nullptr) {
786 return false;
787 } else {
788 return true;
789 }
790 }
791
792 address ArchiveBuilder::get_buffered_addr(address src_addr) const {
793 SourceObjInfo* p = _src_obj_table.get(src_addr);
794 assert(p != nullptr, "src_addr " INTPTR_FORMAT " is used but has not been archived",
795 p2i(src_addr));
796
797 return p->buffered_addr();
798 }
799
800 bool ArchiveBuilder::has_been_archived(address src_addr) const {
801 SourceObjInfo* p = _src_obj_table.get(src_addr);
802 return (p != nullptr);
803 }
804
805 address ArchiveBuilder::get_source_addr(address buffered_addr) const {
806 assert(is_in_buffer_space(buffered_addr), "must be");
807 address* src_p = _buffered_to_src_table.get(buffered_addr);
808 assert(src_p != nullptr && *src_p != nullptr, "must be");
809 return *src_p;
810 }
811
812 void ArchiveBuilder::relocate_embedded_pointers(ArchiveBuilder::SourceObjList* src_objs) {
813 for (int i = 0; i < src_objs->objs()->length(); i++) {
814 src_objs->relocate(i, this);
815 }
816 }
817
818 void ArchiveBuilder::relocate_metaspaceobj_embedded_pointers() {
819 log_info(cds)("Relocating embedded pointers in core regions ... ");
820 relocate_embedded_pointers(&_rw_src_objs);
821 relocate_embedded_pointers(&_ro_src_objs);
822 }
823
824 #define ADD_COUNT(x) \
998 log_info(cds)(" boot " STATS_FORMAT, STATS_PARAMS(boot_klasses));
999 log_info(cds)(" vm " STATS_FORMAT, STATS_PARAMS(vm_klasses));
1000 log_info(cds)(" platform " STATS_FORMAT, STATS_PARAMS(platform_klasses));
1001 log_info(cds)(" app " STATS_FORMAT, STATS_PARAMS(app_klasses));
1002 log_info(cds)(" unregistered " STATS_FORMAT, STATS_PARAMS(unregistered_klasses));
1003 log_info(cds)(" (enum) " STATS_FORMAT, STATS_PARAMS(enum_klasses));
1004 log_info(cds)(" (hidden) " STATS_FORMAT, STATS_PARAMS(hidden_klasses));
1005 log_info(cds)(" (old) " STATS_FORMAT, STATS_PARAMS(old_klasses));
1006 log_info(cds)(" (unlinked) = %5d, boot = %d, plat = %d, app = %d, unreg = %d",
1007 num_unlinked_klasses, boot_unlinked, platform_unlinked, app_unlinked, unreg_unlinked);
1008 log_info(cds)(" obj array classes = %5d", num_obj_array_klasses);
1009 log_info(cds)(" type array classes = %5d", num_type_array_klasses);
1010 log_info(cds)(" symbols = %5d", _symbols->length());
1011
1012 #undef STATS_FORMAT
1013 #undef STATS_PARAMS
1014
1015 DynamicArchive::make_array_klasses_shareable();
1016 }
1017
1018 void ArchiveBuilder::make_training_data_shareable() {
1019 auto clean_td = [&] (address& src_obj, SourceObjInfo& info) {
1020 if (!is_in_buffer_space(info.buffered_addr())) {
1021 return;
1022 }
1023
1024 if (info.msotype() == MetaspaceObj::KlassTrainingDataType ||
1025 info.msotype() == MetaspaceObj::MethodTrainingDataType ||
1026 info.msotype() == MetaspaceObj::CompileTrainingDataType) {
1027 TrainingData* buffered_td = (TrainingData*)info.buffered_addr();
1028 buffered_td->remove_unshareable_info();
1029 } else if (info.msotype() == MetaspaceObj::MethodDataType) {
1030 MethodData* buffered_mdo = (MethodData*)info.buffered_addr();
1031 buffered_mdo->remove_unshareable_info();
1032 } else if (info.msotype() == MetaspaceObj::MethodCountersType) {
1033 MethodCounters* buffered_mc = (MethodCounters*)info.buffered_addr();
1034 buffered_mc->remove_unshareable_info();
1035 }
1036 };
1037 _src_obj_table.iterate_all(clean_td);
1038 }
1039
1040 void ArchiveBuilder::serialize_dynamic_archivable_items(SerializeClosure* soc) {
1041 SymbolTable::serialize_shared_table_header(soc, false);
1042 SystemDictionaryShared::serialize_dictionary_headers(soc, false);
1043 DynamicArchive::serialize_array_klasses(soc);
1044 AOTLinkedClassBulkLoader::serialize(soc, false);
1045 FinalImageRecipes::serialize(soc, false);
1046 TrainingData::serialize_training_data(soc);
1047 }
1048
1049 uintx ArchiveBuilder::buffer_to_offset(address p) const {
1050 address requested_p = to_requested(p);
1051 assert(requested_p >= _requested_static_archive_bottom, "must be");
1052 return requested_p - _requested_static_archive_bottom;
1053 }
1054
1055 uintx ArchiveBuilder::any_to_offset(address p) const {
1056 if (is_in_mapped_static_archive(p)) {
1057 assert(CDSConfig::is_dumping_dynamic_archive(), "must be");
1058 return p - _mapped_static_archive_bottom;
1059 }
1060 if (!is_in_buffer_space(p)) {
1061 // p must be a "source" address
1062 p = get_buffered_addr(p);
1063 }
1064 return buffer_to_offset(p);
1065 }
1066
1067 void ArchiveBuilder::start_cc_region() {
1068 ro_region()->pack();
1069 start_dump_region(&_cc_region);
1070 }
1071
1072 void ArchiveBuilder::end_cc_region() {
1073 _cc_region.pack();
1074 }
1075
1076 address ArchiveBuilder::offset_to_buffered_address(u4 offset) const {
1077 address requested_addr = _requested_static_archive_bottom + offset;
1078 address buffered_addr = requested_addr - _buffer_to_requested_delta;
1079 assert(is_in_buffer_space(buffered_addr), "bad offset");
1080 return buffered_addr;
1081 }
1082
1083 #if INCLUDE_CDS_JAVA_HEAP
1084 narrowKlass ArchiveBuilder::get_requested_narrow_klass(Klass* k) {
1085 assert(CDSConfig::is_dumping_heap(), "sanity");
1086 k = get_buffered_klass(k);
1087 Klass* requested_k = to_requested(k);
1088 const int narrow_klass_shift = ArchiveBuilder::precomputed_narrow_klass_shift();
1089 #ifdef ASSERT
1090 const size_t klass_alignment = MAX2(SharedSpaceObjectAlignment, (size_t)nth_bit(narrow_klass_shift));
1091 assert(is_aligned(k, klass_alignment), "Klass " PTR_FORMAT " misaligned.", p2i(k));
1092 #endif
1093 address narrow_klass_base = _requested_static_archive_bottom; // runtime encoding base == runtime mapping start
1094 // Note: use the "raw" version of encode that takes explicit narrow klass base and shift. Don't use any
1095 // of the variants that do sanity checks, nor any of those that use the current - dump - JVM's encoding setting.
1172 ArchivePtrMarker::compact(_max_non_null_offset);
1173 }
1174 };
1175
1176 #ifdef _LP64
1177 int ArchiveBuilder::precomputed_narrow_klass_shift() {
1178 // Legacy Mode:
1179 // We use 32 bits for narrowKlass, which should cover the full 4G Klass range. Shift can be 0.
1180 // CompactObjectHeader Mode:
1181 // narrowKlass is much smaller, and we use the highest possible shift value to later get the maximum
1182 // Klass encoding range.
1183 //
1184 // Note that all of this may change in the future, if we decide to correct the pre-calculated
1185 // narrow Klass IDs at archive load time.
1186 assert(UseCompressedClassPointers, "Only needed for compressed class pointers");
1187 return UseCompactObjectHeaders ? CompressedKlassPointers::max_shift() : 0;
1188 }
1189 #endif // _LP64
1190
1191 void ArchiveBuilder::relocate_to_requested() {
1192 if (!ro_region()->is_packed()) {
1193 ro_region()->pack();
1194 }
1195
1196 size_t my_archive_size = buffer_top() - buffer_bottom();
1197
1198 if (CDSConfig::is_dumping_static_archive()) {
1199 _requested_static_archive_top = _requested_static_archive_bottom + my_archive_size;
1200 RelocateBufferToRequested<true> patcher(this);
1201 patcher.doit();
1202 } else {
1203 assert(CDSConfig::is_dumping_dynamic_archive(), "must be");
1204 _requested_dynamic_archive_top = _requested_dynamic_archive_bottom + my_archive_size;
1205 RelocateBufferToRequested<false> patcher(this);
1206 patcher.doit();
1207 }
1208 }
1209
1210 // Write detailed info to a mapfile to analyze contents of the archive.
1211 // static dump:
1212 // java -Xshare:dump -Xlog:cds+map=trace:file=cds.map:none:filesize=0
1213 // dynamic dump:
1214 // java -cp MyApp.jar -XX:ArchiveClassesAtExit=MyApp.jsa \
1436 ArchiveBuilder* builder = ArchiveBuilder::current();
1437 Klass* requested_klass = builder->to_requested(builder->get_buffered_addr(source_klass));
1438
1439 st.print(" - klass: ");
1440 source_klass->print_value_on(&st);
1441 st.print(" " PTR_FORMAT, p2i(requested_klass));
1442 st.cr();
1443
1444 if (source_oop->is_typeArray()) {
1445 TypeArrayKlass::cast(source_klass)->oop_print_elements_on(typeArrayOop(source_oop), &st);
1446 } else if (source_oop->is_objArray()) {
1447 objArrayOop source_obj_array = objArrayOop(source_oop);
1448 for (int i = 0; i < source_obj_array->length(); i++) {
1449 st.print(" -%4d: ", i);
1450 print_oop_with_requested_addr_cr(&st, source_obj_array->obj_at(i));
1451 }
1452 } else {
1453 st.print_cr(" - fields (" SIZE_FORMAT " words):", source_oop->size());
1454 ArchivedFieldPrinter print_field(heap_info, &st, source_oop, buffered_addr);
1455 InstanceKlass::cast(source_klass)->print_nonstatic_fields(&print_field);
1456
1457 if (java_lang_Class::is_instance(source_oop)) {
1458 st.print(" - signature: ");
1459 if (java_lang_Class::is_primitive(source_oop)) {
1460 st.print("primitive ??");
1461 } else {
1462 java_lang_Class::print_signature(source_oop, &st);
1463 }
1464 st.cr();
1465 }
1466 }
1467 }
1468 }
1469
1470 static void log_heap_roots() {
1471 LogStreamHandle(Trace, cds, map, oops) st;
1472 if (st.is_enabled()) {
1473 for (int i = 0; i < HeapShared::pending_roots()->length(); i++) {
1474 st.print("roots[%4d]: ", i);
1475 print_oop_with_requested_addr_cr(&st, HeapShared::pending_roots()->at(i).resolve());
1476 }
1477 }
1478 }
1479
1480 // The output looks like this. The first number is the requested address. The second number is
1481 // the narrowOop version of the requested address.
1482 // 0x00000007ffc7e840 (0xfff8fd08) java.lang.Class
1483 // 0x00000007ffc000f8 (0xfff8001f) [B length: 11
1484 static void print_oop_with_requested_addr_cr(outputStream* st, oop source_oop, bool print_addr = true) {
1485 if (source_oop == nullptr) {
1486 st->print_cr("null");
1487 } else {
1488 ResourceMark rm;
1489 oop requested_obj = ArchiveHeapWriter::source_obj_to_requested_obj(source_oop);
1490 if (print_addr) {
1491 st->print(PTR_FORMAT " ", p2i(requested_obj));
1492 }
1493 if (UseCompressedOops) {
1494 st->print("(0x%08x) ", CompressedOops::narrow_oop_value(requested_obj));
1495 }
1496 if (source_oop->is_array()) {
1497 int array_len = arrayOop(source_oop)->length();
1498 st->print_cr("%s length: %d", source_oop->klass()->external_name(), array_len);
1499 } else {
1500 st->print("%s", source_oop->klass()->external_name());
1501 if (java_lang_invoke_MethodType::is_instance(source_oop)) {
1502 st->print(" ");
1503 java_lang_invoke_MethodType::print_signature(source_oop, st);
1504 }
1505 st->cr();
1506 }
1507 }
1508 }
1509 #endif // INCLUDE_CDS_JAVA_HEAP
1510
1511 // Log all the data [base...top). Pretend that the base address
1512 // will be mapped to requested_base at run-time.
1513 static void log_as_hex(address base, address top, address requested_base, bool is_heap = false) {
1514 assert(top >= base, "must be");
1515
1516 LogStreamHandle(Trace, cds, map) lsh;
1517 if (lsh.is_enabled()) {
1518 int unitsize = sizeof(address);
1519 if (is_heap && UseCompressedOops) {
1520 // This makes the compressed oop pointers easier to read, but
1521 // longs and doubles will be split into two words.
1522 unitsize = sizeof(narrowOop);
1523 }
1524 os::print_hex_dump(&lsh, base, top, unitsize, /* print_ascii=*/true, /* bytes_per_line=*/32, requested_base);
1525 }
1558 if (heap_info->is_used()) {
1559 log_heap_region(heap_info);
1560 }
1561 #endif
1562
1563 log_info(cds, map)("[End of CDS archive map]");
1564 }
1565 }; // end ArchiveBuilder::CDSMapLogger
1566
1567 void ArchiveBuilder::print_stats() {
1568 _alloc_stats.print_stats(int(_ro_region.used()), int(_rw_region.used()));
1569 }
1570
1571 void ArchiveBuilder::write_archive(FileMapInfo* mapinfo, ArchiveHeapInfo* heap_info) {
1572 // Make sure NUM_CDS_REGIONS (exported in cds.h) agrees with
1573 // MetaspaceShared::n_regions (internal to hotspot).
1574 assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity");
1575
1576 write_region(mapinfo, MetaspaceShared::rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
1577 write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
1578 write_region(mapinfo, MetaspaceShared::cc, &_cc_region, /*read_only=*/false,/*allow_exec=*/false);
1579
1580 // Split pointer map into read-write and read-only bitmaps
1581 ArchivePtrMarker::initialize_rw_ro_cc_maps(&_rw_ptrmap, &_ro_ptrmap, &_cc_ptrmap);
1582
1583 size_t bitmap_size_in_bytes;
1584 char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::rw_ptrmap(),
1585 ArchivePtrMarker::ro_ptrmap(),
1586 ArchivePtrMarker::cc_ptrmap(),
1587 heap_info,
1588 bitmap_size_in_bytes);
1589
1590 if (heap_info->is_used()) {
1591 _total_heap_region_size = mapinfo->write_heap_region(heap_info);
1592 }
1593
1594 print_region_stats(mapinfo, heap_info);
1595
1596 mapinfo->set_requested_base((char*)MetaspaceShared::requested_base_address());
1597 mapinfo->set_header_crc(mapinfo->compute_header_crc());
1598 // After this point, we should not write any data into mapinfo->header() since this
1599 // would corrupt its checksum we have calculated before.
1600 mapinfo->write_header();
1601 mapinfo->close();
1602
1603 if (log_is_enabled(Info, cds)) {
1604 print_stats();
1605 }
1606
1607 if (log_is_enabled(Info, cds, map)) {
1613 }
1614
1615 void ArchiveBuilder::write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only, bool allow_exec) {
1616 mapinfo->write_region(region_idx, dump_region->base(), dump_region->used(), read_only, allow_exec);
1617 }
1618
1619 void ArchiveBuilder::print_region_stats(FileMapInfo *mapinfo, ArchiveHeapInfo* heap_info) {
1620 // Print statistics of all the regions
1621 const size_t bitmap_used = mapinfo->region_at(MetaspaceShared::bm)->used();
1622 const size_t bitmap_reserved = mapinfo->region_at(MetaspaceShared::bm)->used_aligned();
1623 const size_t total_reserved = _ro_region.reserved() + _rw_region.reserved() +
1624 bitmap_reserved +
1625 _total_heap_region_size;
1626 const size_t total_bytes = _ro_region.used() + _rw_region.used() +
1627 bitmap_used +
1628 _total_heap_region_size;
1629 const double total_u_perc = percent_of(total_bytes, total_reserved);
1630
1631 _rw_region.print(total_reserved);
1632 _ro_region.print(total_reserved);
1633 _cc_region.print(total_reserved);
1634
1635 print_bitmap_region_stats(bitmap_used, total_reserved);
1636
1637 if (heap_info->is_used()) {
1638 print_heap_region_stats(heap_info, total_reserved);
1639 }
1640
1641 log_debug(cds)("total : " SIZE_FORMAT_W(9) " [100.0%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used]",
1642 total_bytes, total_reserved, total_u_perc);
1643 }
1644
1645 void ArchiveBuilder::print_bitmap_region_stats(size_t size, size_t total_size) {
1646 log_debug(cds)("bm space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [100.0%% used]",
1647 size, size/double(total_size)*100.0, size);
1648 }
1649
1650 void ArchiveBuilder::print_heap_region_stats(ArchiveHeapInfo *info, size_t total_size) {
1651 char* start = info->buffer_start();
1652 size_t size = info->buffer_byte_size();
1653 char* top = start + size;
|