jdk

Форк
0
/
heapShared.cpp 
1739 строк · 64.1 Кб
1
/*
2
 * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
 *
5
 * This code is free software; you can redistribute it and/or modify it
6
 * under the terms of the GNU General Public License version 2 only, as
7
 * published by the Free Software Foundation.
8
 *
9
 * This code is distributed in the hope that it will be useful, but WITHOUT
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
 * version 2 for more details (a copy is included in the LICENSE file that
13
 * accompanied this code).
14
 *
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/archiveBuilder.hpp"
27
#include "cds/archiveHeapLoader.hpp"
28
#include "cds/archiveHeapWriter.hpp"
29
#include "cds/archiveUtils.hpp"
30
#include "cds/cdsConfig.hpp"
31
#include "cds/cdsEnumKlass.hpp"
32
#include "cds/cdsHeapVerifier.hpp"
33
#include "cds/heapShared.hpp"
34
#include "cds/metaspaceShared.hpp"
35
#include "classfile/classLoaderData.hpp"
36
#include "classfile/javaClasses.inline.hpp"
37
#include "classfile/modules.hpp"
38
#include "classfile/stringTable.hpp"
39
#include "classfile/symbolTable.hpp"
40
#include "classfile/systemDictionary.hpp"
41
#include "classfile/systemDictionaryShared.hpp"
42
#include "classfile/vmClasses.hpp"
43
#include "classfile/vmSymbols.hpp"
44
#include "gc/shared/collectedHeap.hpp"
45
#include "gc/shared/gcLocker.hpp"
46
#include "gc/shared/gcVMOperations.hpp"
47
#include "logging/log.hpp"
48
#include "logging/logStream.hpp"
49
#include "memory/iterator.inline.hpp"
50
#include "memory/resourceArea.hpp"
51
#include "memory/universe.hpp"
52
#include "oops/compressedOops.inline.hpp"
53
#include "oops/fieldStreams.inline.hpp"
54
#include "oops/objArrayOop.inline.hpp"
55
#include "oops/oop.inline.hpp"
56
#include "oops/typeArrayOop.inline.hpp"
57
#include "prims/jvmtiExport.hpp"
58
#include "runtime/fieldDescriptor.inline.hpp"
59
#include "runtime/init.hpp"
60
#include "runtime/javaCalls.hpp"
61
#include "runtime/mutexLocker.hpp"
62
#include "runtime/safepointVerifiers.hpp"
63
#include "utilities/bitMap.inline.hpp"
64
#include "utilities/copy.hpp"
65
#if INCLUDE_G1GC
66
#include "gc/g1/g1CollectedHeap.hpp"
67
#endif
68

69
#if INCLUDE_CDS_JAVA_HEAP
70

71
struct ArchivableStaticFieldInfo {
72
  const char* klass_name;
73
  const char* field_name;
74
  InstanceKlass* klass;
75
  int offset;
76
  BasicType type;
77

78
  ArchivableStaticFieldInfo(const char* k, const char* f)
79
  : klass_name(k), field_name(f), klass(nullptr), offset(0), type(T_ILLEGAL) {}
80

81
  bool valid() {
82
    return klass_name != nullptr;
83
  }
84
};
85

86
bool HeapShared::_disable_writing = false;
87
DumpedInternedStrings *HeapShared::_dumped_interned_strings = nullptr;
88

89
size_t HeapShared::_alloc_count[HeapShared::ALLOC_STAT_SLOTS];
90
size_t HeapShared::_alloc_size[HeapShared::ALLOC_STAT_SLOTS];
91
size_t HeapShared::_total_obj_count;
92
size_t HeapShared::_total_obj_size;
93

94
#ifndef PRODUCT
95
#define ARCHIVE_TEST_FIELD_NAME "archivedObjects"
96
static Array<char>* _archived_ArchiveHeapTestClass = nullptr;
97
static const char* _test_class_name = nullptr;
98
static const Klass* _test_class = nullptr;
99
static const ArchivedKlassSubGraphInfoRecord* _test_class_record = nullptr;
100
#endif
101

102

103
//
104
// If you add new entries to the following tables, you should know what you're doing!
105
//
106

107
static ArchivableStaticFieldInfo archive_subgraph_entry_fields[] = {
108
  {"java/lang/Integer$IntegerCache",              "archivedCache"},
109
  {"java/lang/Long$LongCache",                    "archivedCache"},
110
  {"java/lang/Byte$ByteCache",                    "archivedCache"},
111
  {"java/lang/Short$ShortCache",                  "archivedCache"},
112
  {"java/lang/Character$CharacterCache",          "archivedCache"},
113
  {"java/util/jar/Attributes$Name",               "KNOWN_NAMES"},
114
  {"sun/util/locale/BaseLocale",                  "constantBaseLocales"},
115
  {"jdk/internal/module/ArchivedModuleGraph",     "archivedModuleGraph"},
116
  {"java/util/ImmutableCollections",              "archivedObjects"},
117
  {"java/lang/ModuleLayer",                       "EMPTY_LAYER"},
118
  {"java/lang/module/Configuration",              "EMPTY_CONFIGURATION"},
119
  {"jdk/internal/math/FDBigInteger",              "archivedCaches"},
120
#ifndef PRODUCT
121
  {nullptr, nullptr}, // Extra slot for -XX:ArchiveHeapTestClass
122
#endif
123
  {nullptr, nullptr},
124
};
125

126
// full module graph
127
static ArchivableStaticFieldInfo fmg_archive_subgraph_entry_fields[] = {
128
  {"jdk/internal/loader/ArchivedClassLoaders",    "archivedClassLoaders"},
129
  {ARCHIVED_BOOT_LAYER_CLASS,                     ARCHIVED_BOOT_LAYER_FIELD},
130
  {"java/lang/Module$ArchivedData",               "archivedData"},
131
  {nullptr, nullptr},
132
};
133

134
KlassSubGraphInfo* HeapShared::_default_subgraph_info;
135
GrowableArrayCHeap<oop, mtClassShared>* HeapShared::_pending_roots = nullptr;
136
OopHandle HeapShared::_roots;
137
OopHandle HeapShared::_scratch_basic_type_mirrors[T_VOID+1];
138
MetaspaceObjToOopHandleTable* HeapShared::_scratch_java_mirror_table = nullptr;
139
MetaspaceObjToOopHandleTable* HeapShared::_scratch_references_table = nullptr;
140

141
static bool is_subgraph_root_class_of(ArchivableStaticFieldInfo fields[], InstanceKlass* ik) {
142
  for (int i = 0; fields[i].valid(); i++) {
143
    if (fields[i].klass == ik) {
144
      return true;
145
    }
146
  }
147
  return false;
148
}
149

150
bool HeapShared::is_subgraph_root_class(InstanceKlass* ik) {
151
  return is_subgraph_root_class_of(archive_subgraph_entry_fields, ik) ||
152
         is_subgraph_root_class_of(fmg_archive_subgraph_entry_fields, ik);
153
}
154

155
unsigned HeapShared::oop_hash(oop const& p) {
156
  // Do not call p->identity_hash() as that will update the
157
  // object header.
158
  return primitive_hash(cast_from_oop<intptr_t>(p));
159
}
160

161
static void reset_states(oop obj, TRAPS) {
162
  Handle h_obj(THREAD, obj);
163
  InstanceKlass* klass = InstanceKlass::cast(obj->klass());
164
  TempNewSymbol method_name = SymbolTable::new_symbol("resetArchivedStates");
165
  Symbol* method_sig = vmSymbols::void_method_signature();
166

167
  while (klass != nullptr) {
168
    Method* method = klass->find_method(method_name, method_sig);
169
    if (method != nullptr) {
170
      assert(method->is_private(), "must be");
171
      if (log_is_enabled(Debug, cds)) {
172
        ResourceMark rm(THREAD);
173
        log_debug(cds)("  calling %s", method->name_and_sig_as_C_string());
174
      }
175
      JavaValue result(T_VOID);
176
      JavaCalls::call_special(&result, h_obj, klass,
177
                              method_name, method_sig, CHECK);
178
    }
179
    klass = klass->java_super();
180
  }
181
}
182

183
void HeapShared::reset_archived_object_states(TRAPS) {
184
  assert(CDSConfig::is_dumping_heap(), "dump-time only");
185
  log_debug(cds)("Resetting platform loader");
186
  reset_states(SystemDictionary::java_platform_loader(), CHECK);
187
  log_debug(cds)("Resetting system loader");
188
  reset_states(SystemDictionary::java_system_loader(), CHECK);
189

190
  // Clean up jdk.internal.loader.ClassLoaders::bootLoader(), which is not
191
  // directly used for class loading, but rather is used by the core library
192
  // to keep track of resources, etc, loaded by the null class loader.
193
  //
194
  // Note, this object is non-null, and is not the same as
195
  // ClassLoaderData::the_null_class_loader_data()->class_loader(),
196
  // which is null.
197
  log_debug(cds)("Resetting boot loader");
198
  JavaValue result(T_OBJECT);
199
  JavaCalls::call_static(&result,
200
                         vmClasses::jdk_internal_loader_ClassLoaders_klass(),
201
                         vmSymbols::bootLoader_name(),
202
                         vmSymbols::void_BuiltinClassLoader_signature(),
203
                         CHECK);
204
  Handle boot_loader(THREAD, result.get_oop());
205
  reset_states(boot_loader(), CHECK);
206
}
207

208
HeapShared::ArchivedObjectCache* HeapShared::_archived_object_cache = nullptr;
209

210
bool HeapShared::has_been_archived(oop obj) {
211
  assert(CDSConfig::is_dumping_heap(), "dump-time only");
212
  return archived_object_cache()->get(obj) != nullptr;
213
}
214

215
int HeapShared::append_root(oop obj) {
216
  assert(CDSConfig::is_dumping_heap(), "dump-time only");
217

218
  // No GC should happen since we aren't scanning _pending_roots.
219
  assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread");
220

221
  if (_pending_roots == nullptr) {
222
    _pending_roots = new GrowableArrayCHeap<oop, mtClassShared>(500);
223
  }
224

225
  return _pending_roots->append(obj);
226
}
227

228
objArrayOop HeapShared::roots() {
229
  if (CDSConfig::is_dumping_heap()) {
230
    assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread");
231
    if (!HeapShared::can_write()) {
232
      return nullptr;
233
    }
234
  } else {
235
    assert(CDSConfig::is_using_archive(), "must be");
236
  }
237

238
  objArrayOop roots = (objArrayOop)_roots.resolve();
239
  assert(roots != nullptr, "should have been initialized");
240
  return roots;
241
}
242

243
// Returns an objArray that contains all the roots of the archived objects
244
oop HeapShared::get_root(int index, bool clear) {
245
  assert(index >= 0, "sanity");
246
  assert(!CDSConfig::is_dumping_heap() && CDSConfig::is_using_archive(), "runtime only");
247
  assert(!_roots.is_empty(), "must have loaded shared heap");
248
  oop result = roots()->obj_at(index);
249
  if (clear) {
250
    clear_root(index);
251
  }
252
  return result;
253
}
254

255
void HeapShared::clear_root(int index) {
256
  assert(index >= 0, "sanity");
257
  assert(CDSConfig::is_using_archive(), "must be");
258
  if (ArchiveHeapLoader::is_in_use()) {
259
    if (log_is_enabled(Debug, cds, heap)) {
260
      oop old = roots()->obj_at(index);
261
      log_debug(cds, heap)("Clearing root %d: was " PTR_FORMAT, index, p2i(old));
262
    }
263
    roots()->obj_at_put(index, nullptr);
264
  }
265
}
266

267
bool HeapShared::archive_object(oop obj) {
268
  assert(CDSConfig::is_dumping_heap(), "dump-time only");
269

270
  assert(!obj->is_stackChunk(), "do not archive stack chunks");
271
  if (has_been_archived(obj)) {
272
    return true;
273
  }
274

275
  if (ArchiveHeapWriter::is_too_large_to_archive(obj->size())) {
276
    log_debug(cds, heap)("Cannot archive, object (" PTR_FORMAT ") is too large: " SIZE_FORMAT,
277
                         p2i(obj), obj->size());
278
    return false;
279
  } else {
280
    count_allocation(obj->size());
281
    ArchiveHeapWriter::add_source_obj(obj);
282
    CachedOopInfo info = make_cached_oop_info(obj);
283
    archived_object_cache()->put_when_absent(obj, info);
284
    archived_object_cache()->maybe_grow();
285
    mark_native_pointers(obj);
286

287
    if (log_is_enabled(Debug, cds, heap)) {
288
      ResourceMark rm;
289
      log_debug(cds, heap)("Archived heap object " PTR_FORMAT " : %s",
290
                           p2i(obj), obj->klass()->external_name());
291
    }
292

293
    if (java_lang_Module::is_instance(obj) && Modules::check_archived_module_oop(obj)) {
294
      Modules::update_oops_in_archived_module(obj, append_root(obj));
295
    }
296

297
    return true;
298
  }
299
}
300

301
class MetaspaceObjToOopHandleTable: public ResourceHashtable<MetaspaceObj*, OopHandle,
302
    36137, // prime number
303
    AnyObj::C_HEAP,
304
    mtClassShared> {
305
public:
306
  oop get_oop(MetaspaceObj* ptr) {
307
    MutexLocker ml(ScratchObjects_lock, Mutex::_no_safepoint_check_flag);
308
    OopHandle* handle = get(ptr);
309
    if (handle != nullptr) {
310
      return handle->resolve();
311
    } else {
312
      return nullptr;
313
    }
314
  }
315
  void set_oop(MetaspaceObj* ptr, oop o) {
316
    MutexLocker ml(ScratchObjects_lock, Mutex::_no_safepoint_check_flag);
317
    OopHandle handle(Universe::vm_global(), o);
318
    bool is_new = put(ptr, handle);
319
    assert(is_new, "cannot set twice");
320
  }
321
  void remove_oop(MetaspaceObj* ptr) {
322
    MutexLocker ml(ScratchObjects_lock, Mutex::_no_safepoint_check_flag);
323
    OopHandle* handle = get(ptr);
324
    if (handle != nullptr) {
325
      handle->release(Universe::vm_global());
326
      remove(ptr);
327
    }
328
  }
329
};
330

331
void HeapShared::add_scratch_resolved_references(ConstantPool* src, objArrayOop dest) {
332
  _scratch_references_table->set_oop(src, dest);
333
}
334

335
objArrayOop HeapShared::scratch_resolved_references(ConstantPool* src) {
336
  return (objArrayOop)_scratch_references_table->get_oop(src);
337
}
338

339
void HeapShared::init_scratch_objects(TRAPS) {
340
  for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
341
    BasicType bt = (BasicType)i;
342
    if (!is_reference_type(bt)) {
343
      oop m = java_lang_Class::create_basic_type_mirror(type2name(bt), bt, CHECK);
344
      _scratch_basic_type_mirrors[i] = OopHandle(Universe::vm_global(), m);
345
    }
346
  }
347
  _scratch_java_mirror_table = new (mtClass)MetaspaceObjToOopHandleTable();
348
  _scratch_references_table = new (mtClass)MetaspaceObjToOopHandleTable();
349
}
350

351
oop HeapShared::scratch_java_mirror(BasicType t) {
352
  assert((uint)t < T_VOID+1, "range check");
353
  assert(!is_reference_type(t), "sanity");
354
  return _scratch_basic_type_mirrors[t].resolve();
355
}
356

357
oop HeapShared::scratch_java_mirror(Klass* k) {
358
  return _scratch_java_mirror_table->get_oop(k);
359
}
360

361
void HeapShared::set_scratch_java_mirror(Klass* k, oop mirror) {
362
  _scratch_java_mirror_table->set_oop(k, mirror);
363
}
364

365
void HeapShared::remove_scratch_objects(Klass* k) {
366
  _scratch_java_mirror_table->remove_oop(k);
367
  if (k->is_instance_klass()) {
368
    _scratch_references_table->remove(InstanceKlass::cast(k)->constants());
369
  }
370
}
371

372
void HeapShared::archive_java_mirrors() {
373
  for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
374
    BasicType bt = (BasicType)i;
375
    if (!is_reference_type(bt)) {
376
      oop m = _scratch_basic_type_mirrors[i].resolve();
377
      assert(m != nullptr, "sanity");
378
      bool success = archive_reachable_objects_from(1, _default_subgraph_info, m);
379
      assert(success, "sanity");
380

381
      log_trace(cds, heap, mirror)(
382
        "Archived %s mirror object from " PTR_FORMAT,
383
        type2name(bt), p2i(m));
384

385
      Universe::set_archived_basic_type_mirror_index(bt, append_root(m));
386
    }
387
  }
388

389
  GrowableArray<Klass*>* klasses = ArchiveBuilder::current()->klasses();
390
  assert(klasses != nullptr, "sanity");
391
  for (int i = 0; i < klasses->length(); i++) {
392
    Klass* orig_k = klasses->at(i);
393
    oop m = scratch_java_mirror(orig_k);
394
    if (m != nullptr) {
395
      Klass* buffered_k = ArchiveBuilder::get_buffered_klass(orig_k);
396
      bool success = archive_reachable_objects_from(1, _default_subgraph_info, m);
397
      guarantee(success, "scratch mirrors must point to only archivable objects");
398
      buffered_k->set_archived_java_mirror(append_root(m));
399
      ResourceMark rm;
400
      log_trace(cds, heap, mirror)(
401
        "Archived %s mirror object from " PTR_FORMAT,
402
        buffered_k->external_name(), p2i(m));
403

404
      // archive the resolved_referenes array
405
      if (buffered_k->is_instance_klass()) {
406
        InstanceKlass* ik = InstanceKlass::cast(buffered_k);
407
        oop rr = ik->constants()->prepare_resolved_references_for_archiving();
408
        if (rr != nullptr && !ArchiveHeapWriter::is_too_large_to_archive(rr)) {
409
          bool success = HeapShared::archive_reachable_objects_from(1, _default_subgraph_info, rr);
410
          assert(success, "must be");
411
          int root_index = append_root(rr);
412
          ik->constants()->cache()->set_archived_references(root_index);
413
        }
414
      }
415
    }
416
  }
417
}
418

419
void HeapShared::archive_strings() {
420
  oop shared_strings_array = StringTable::init_shared_table(_dumped_interned_strings);
421
  bool success = archive_reachable_objects_from(1, _default_subgraph_info, shared_strings_array);
422
  // We must succeed because:
423
  // - _dumped_interned_strings do not contain any large strings.
424
  // - StringTable::init_shared_table() doesn't create any large arrays.
425
  assert(success, "shared strings array must not point to arrays or strings that are too large to archive");
426
  StringTable::set_shared_strings_array_index(append_root(shared_strings_array));
427
}
428

429
int HeapShared::archive_exception_instance(oop exception) {
430
  bool success = archive_reachable_objects_from(1, _default_subgraph_info, exception);
431
  assert(success, "sanity");
432
  return append_root(exception);
433
}
434

435
void HeapShared::mark_native_pointers(oop orig_obj) {
436
  if (java_lang_Class::is_instance(orig_obj)) {
437
    ArchiveHeapWriter::mark_native_pointer(orig_obj, java_lang_Class::klass_offset());
438
    ArchiveHeapWriter::mark_native_pointer(orig_obj, java_lang_Class::array_klass_offset());
439
  }
440
}
441

442
void HeapShared::get_pointer_info(oop src_obj, bool& has_oop_pointers, bool& has_native_pointers) {
443
  CachedOopInfo* info = archived_object_cache()->get(src_obj);
444
  assert(info != nullptr, "must be");
445
  has_oop_pointers = info->has_oop_pointers();
446
  has_native_pointers = info->has_native_pointers();
447
}
448

449
void HeapShared::set_has_native_pointers(oop src_obj) {
450
  CachedOopInfo* info = archived_object_cache()->get(src_obj);
451
  assert(info != nullptr, "must be");
452
  info->set_has_native_pointers();
453
}
454

455
void HeapShared::archive_objects(ArchiveHeapInfo *heap_info) {
456
  {
457
    NoSafepointVerifier nsv;
458

459
    _default_subgraph_info = init_subgraph_info(vmClasses::Object_klass(), false);
460

461
    // Cache for recording where the archived objects are copied to
462
    create_archived_object_cache();
463

464
    log_info(cds)("Heap range = [" PTR_FORMAT " - "  PTR_FORMAT "]",
465
                   UseCompressedOops ? p2i(CompressedOops::begin()) :
466
                                       p2i((address)G1CollectedHeap::heap()->reserved().start()),
467
                   UseCompressedOops ? p2i(CompressedOops::end()) :
468
                                       p2i((address)G1CollectedHeap::heap()->reserved().end()));
469
    copy_objects();
470

471
    CDSHeapVerifier::verify();
472
    check_default_subgraph_classes();
473
  }
474

475
  ArchiveHeapWriter::write(_pending_roots, heap_info);
476
}
477

478
void HeapShared::copy_interned_strings() {
479
  init_seen_objects_table();
480

481
  auto copier = [&] (oop s, bool value_ignored) {
482
    assert(s != nullptr, "sanity");
483
    assert(!ArchiveHeapWriter::is_string_too_large_to_archive(s), "large strings must have been filtered");
484
    bool success = archive_reachable_objects_from(1, _default_subgraph_info, s);
485
    assert(success, "must be");
486
    // Prevent string deduplication from changing the value field to
487
    // something not in the archive.
488
    java_lang_String::set_deduplication_forbidden(s);
489
  };
490
  _dumped_interned_strings->iterate_all(copier);
491

492
  delete_seen_objects_table();
493
}
494

495
void HeapShared::copy_special_objects() {
496
  // Archive special objects that do not belong to any subgraphs
497
  init_seen_objects_table();
498
  archive_java_mirrors();
499
  archive_strings();
500
  Universe::archive_exception_instances();
501
  delete_seen_objects_table();
502
}
503

504
void HeapShared::copy_objects() {
505
  assert(HeapShared::can_write(), "must be");
506

507
  copy_interned_strings();
508
  copy_special_objects();
509

510
  archive_object_subgraphs(archive_subgraph_entry_fields,
511
                           false /* is_full_module_graph */);
512

513
  if (CDSConfig::is_dumping_full_module_graph()) {
514
    archive_object_subgraphs(fmg_archive_subgraph_entry_fields,
515
                             true /* is_full_module_graph */);
516
    Modules::verify_archived_modules();
517
  }
518
}
519

520
//
521
// Subgraph archiving support
522
//
523
HeapShared::DumpTimeKlassSubGraphInfoTable* HeapShared::_dump_time_subgraph_info_table = nullptr;
524
HeapShared::RunTimeKlassSubGraphInfoTable   HeapShared::_run_time_subgraph_info_table;
525

526
// Get the subgraph_info for Klass k. A new subgraph_info is created if
527
// there is no existing one for k. The subgraph_info records the "buffered"
528
// address of the class.
529
KlassSubGraphInfo* HeapShared::init_subgraph_info(Klass* k, bool is_full_module_graph) {
530
  assert(CDSConfig::is_dumping_heap(), "dump time only");
531
  bool created;
532
  Klass* buffered_k = ArchiveBuilder::get_buffered_klass(k);
533
  KlassSubGraphInfo* info =
534
    _dump_time_subgraph_info_table->put_if_absent(k, KlassSubGraphInfo(buffered_k, is_full_module_graph),
535
                                                  &created);
536
  assert(created, "must not initialize twice");
537
  return info;
538
}
539

540
KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) {
541
  assert(CDSConfig::is_dumping_heap(), "dump time only");
542
  KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(k);
543
  assert(info != nullptr, "must have been initialized");
544
  return info;
545
}
546

547
// Add an entry field to the current KlassSubGraphInfo.
548
void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) {
549
  assert(CDSConfig::is_dumping_heap(), "dump time only");
550
  if (_subgraph_entry_fields == nullptr) {
551
    _subgraph_entry_fields =
552
      new (mtClass) GrowableArray<int>(10, mtClass);
553
  }
554
  _subgraph_entry_fields->append(static_field_offset);
555
  _subgraph_entry_fields->append(HeapShared::append_root(v));
556
}
557

558
// Add the Klass* for an object in the current KlassSubGraphInfo's subgraphs.
559
// Only objects of boot classes can be included in sub-graph.
560
void KlassSubGraphInfo::add_subgraph_object_klass(Klass* orig_k) {
561
  assert(CDSConfig::is_dumping_heap(), "dump time only");
562
  Klass* buffered_k = ArchiveBuilder::get_buffered_klass(orig_k);
563

564
  if (_subgraph_object_klasses == nullptr) {
565
    _subgraph_object_klasses =
566
      new (mtClass) GrowableArray<Klass*>(50, mtClass);
567
  }
568

569
  assert(ArchiveBuilder::current()->is_in_buffer_space(buffered_k), "must be a shared class");
570

571
  if (_k == buffered_k) {
572
    // Don't add the Klass containing the sub-graph to it's own klass
573
    // initialization list.
574
    return;
575
  }
576

577
  if (buffered_k->is_instance_klass()) {
578
    assert(InstanceKlass::cast(buffered_k)->is_shared_boot_class(),
579
          "must be boot class");
580
    // vmClasses::xxx_klass() are not updated, need to check
581
    // the original Klass*
582
    if (orig_k == vmClasses::String_klass() ||
583
        orig_k == vmClasses::Object_klass()) {
584
      // Initialized early during VM initialization. No need to be added
585
      // to the sub-graph object class list.
586
      return;
587
    }
588
    check_allowed_klass(InstanceKlass::cast(orig_k));
589
  } else if (buffered_k->is_objArray_klass()) {
590
    Klass* abk = ObjArrayKlass::cast(buffered_k)->bottom_klass();
591
    if (abk->is_instance_klass()) {
592
      assert(InstanceKlass::cast(abk)->is_shared_boot_class(),
593
            "must be boot class");
594
      check_allowed_klass(InstanceKlass::cast(ObjArrayKlass::cast(orig_k)->bottom_klass()));
595
    }
596
    if (buffered_k == Universe::objectArrayKlass()) {
597
      // Initialized early during Universe::genesis. No need to be added
598
      // to the list.
599
      return;
600
    }
601
  } else {
602
    assert(buffered_k->is_typeArray_klass(), "must be");
603
    // Primitive type arrays are created early during Universe::genesis.
604
    return;
605
  }
606

607
  if (log_is_enabled(Debug, cds, heap)) {
608
    if (!_subgraph_object_klasses->contains(buffered_k)) {
609
      ResourceMark rm;
610
      log_debug(cds, heap)("Adding klass %s", orig_k->external_name());
611
    }
612
  }
613

614
  _subgraph_object_klasses->append_if_missing(buffered_k);
615
  _has_non_early_klasses |= is_non_early_klass(orig_k);
616
}
617

618
void KlassSubGraphInfo::check_allowed_klass(InstanceKlass* ik) {
619
  if (ik->module()->name() == vmSymbols::java_base()) {
620
    assert(ik->package() != nullptr, "classes in java.base cannot be in unnamed package");
621
    return;
622
  }
623

624
#ifndef PRODUCT
625
  if (!ik->module()->is_named() && ik->package() == nullptr) {
626
    // This class is loaded by ArchiveHeapTestClass
627
    return;
628
  }
629
  const char* extra_msg = ", or in an unnamed package of an unnamed module";
630
#else
631
  const char* extra_msg = "";
632
#endif
633

634
  ResourceMark rm;
635
  log_error(cds, heap)("Class %s not allowed in archive heap. Must be in java.base%s",
636
                       ik->external_name(), extra_msg);
637
  MetaspaceShared::unrecoverable_writing_error();
638
}
639

640
bool KlassSubGraphInfo::is_non_early_klass(Klass* k) {
641
  if (k->is_objArray_klass()) {
642
    k = ObjArrayKlass::cast(k)->bottom_klass();
643
  }
644
  if (k->is_instance_klass()) {
645
    if (!SystemDictionaryShared::is_early_klass(InstanceKlass::cast(k))) {
646
      ResourceMark rm;
647
      log_info(cds, heap)("non-early: %s", k->external_name());
648
      return true;
649
    } else {
650
      return false;
651
    }
652
  } else {
653
    return false;
654
  }
655
}
656

657
// Initialize an archived subgraph_info_record from the given KlassSubGraphInfo.
658
void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) {
659
  _k = info->klass();
660
  _entry_field_records = nullptr;
661
  _subgraph_object_klasses = nullptr;
662
  _is_full_module_graph = info->is_full_module_graph();
663

664
  if (_is_full_module_graph) {
665
    // Consider all classes referenced by the full module graph as early -- we will be
666
    // allocating objects of these classes during JVMTI early phase, so they cannot
667
    // be processed by (non-early) JVMTI ClassFileLoadHook
668
    _has_non_early_klasses = false;
669
  } else {
670
    _has_non_early_klasses = info->has_non_early_klasses();
671
  }
672

673
  if (_has_non_early_klasses) {
674
    ResourceMark rm;
675
    log_info(cds, heap)(
676
          "Subgraph of klass %s has non-early klasses and cannot be used when JVMTI ClassFileLoadHook is enabled",
677
          _k->external_name());
678
  }
679

680
  // populate the entry fields
681
  GrowableArray<int>* entry_fields = info->subgraph_entry_fields();
682
  if (entry_fields != nullptr) {
683
    int num_entry_fields = entry_fields->length();
684
    assert(num_entry_fields % 2 == 0, "sanity");
685
    _entry_field_records =
686
      ArchiveBuilder::new_ro_array<int>(num_entry_fields);
687
    for (int i = 0 ; i < num_entry_fields; i++) {
688
      _entry_field_records->at_put(i, entry_fields->at(i));
689
    }
690
  }
691

692
  // the Klasses of the objects in the sub-graphs
693
  GrowableArray<Klass*>* subgraph_object_klasses = info->subgraph_object_klasses();
694
  if (subgraph_object_klasses != nullptr) {
695
    int num_subgraphs_klasses = subgraph_object_klasses->length();
696
    _subgraph_object_klasses =
697
      ArchiveBuilder::new_ro_array<Klass*>(num_subgraphs_klasses);
698
    for (int i = 0; i < num_subgraphs_klasses; i++) {
699
      Klass* subgraph_k = subgraph_object_klasses->at(i);
700
      if (log_is_enabled(Info, cds, heap)) {
701
        ResourceMark rm;
702
        log_info(cds, heap)(
703
          "Archived object klass %s (%2d) => %s",
704
          _k->external_name(), i, subgraph_k->external_name());
705
      }
706
      _subgraph_object_klasses->at_put(i, subgraph_k);
707
      ArchivePtrMarker::mark_pointer(_subgraph_object_klasses->adr_at(i));
708
    }
709
  }
710

711
  ArchivePtrMarker::mark_pointer(&_k);
712
  ArchivePtrMarker::mark_pointer(&_entry_field_records);
713
  ArchivePtrMarker::mark_pointer(&_subgraph_object_klasses);
714
}
715

716
struct CopyKlassSubGraphInfoToArchive : StackObj {
717
  CompactHashtableWriter* _writer;
718
  CopyKlassSubGraphInfoToArchive(CompactHashtableWriter* writer) : _writer(writer) {}
719

720
  bool do_entry(Klass* klass, KlassSubGraphInfo& info) {
721
    if (info.subgraph_object_klasses() != nullptr || info.subgraph_entry_fields() != nullptr) {
722
      ArchivedKlassSubGraphInfoRecord* record =
723
        (ArchivedKlassSubGraphInfoRecord*)ArchiveBuilder::ro_region_alloc(sizeof(ArchivedKlassSubGraphInfoRecord));
724
      record->init(&info);
725

726
      Klass* buffered_k = ArchiveBuilder::get_buffered_klass(klass);
727
      unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary((address)buffered_k);
728
      u4 delta = ArchiveBuilder::current()->any_to_offset_u4(record);
729
      _writer->add(hash, delta);
730
    }
731
    return true; // keep on iterating
732
  }
733
};
734

735
// Build the records of archived subgraph infos, which include:
736
// - Entry points to all subgraphs from the containing class mirror. The entry
737
//   points are static fields in the mirror. For each entry point, the field
738
//   offset, and value are recorded in the sub-graph
739
//   info. The value is stored back to the corresponding field at runtime.
740
// - A list of klasses that need to be loaded/initialized before archived
741
//   java object sub-graph can be accessed at runtime.
742
void HeapShared::write_subgraph_info_table() {
743
  // Allocate the contents of the hashtable(s) inside the RO region of the CDS archive.
744
  DumpTimeKlassSubGraphInfoTable* d_table = _dump_time_subgraph_info_table;
745
  CompactHashtableStats stats;
746

747
  _run_time_subgraph_info_table.reset();
748

749
  CompactHashtableWriter writer(d_table->_count, &stats);
750
  CopyKlassSubGraphInfoToArchive copy(&writer);
751
  d_table->iterate(&copy);
752
  writer.dump(&_run_time_subgraph_info_table, "subgraphs");
753

754
#ifndef PRODUCT
755
  if (ArchiveHeapTestClass != nullptr) {
756
    size_t len = strlen(ArchiveHeapTestClass) + 1;
757
    Array<char>* array = ArchiveBuilder::new_ro_array<char>((int)len);
758
    strncpy(array->adr_at(0), ArchiveHeapTestClass, len);
759
    _archived_ArchiveHeapTestClass = array;
760
  }
761
#endif
762
  if (log_is_enabled(Info, cds, heap)) {
763
    print_stats();
764
  }
765
}
766

767
void HeapShared::init_roots(oop roots_oop) {
768
  if (roots_oop != nullptr) {
769
    assert(ArchiveHeapLoader::is_in_use(), "must be");
770
    _roots = OopHandle(Universe::vm_global(), roots_oop);
771
  }
772
}
773

774
void HeapShared::serialize_tables(SerializeClosure* soc) {
775

776
#ifndef PRODUCT
777
  soc->do_ptr(&_archived_ArchiveHeapTestClass);
778
  if (soc->reading() && _archived_ArchiveHeapTestClass != nullptr) {
779
    _test_class_name = _archived_ArchiveHeapTestClass->adr_at(0);
780
    setup_test_class(_test_class_name);
781
  }
782
#endif
783

784
  _run_time_subgraph_info_table.serialize_header(soc);
785
}
786

787
static void verify_the_heap(Klass* k, const char* which) {
788
  if (VerifyArchivedFields > 0) {
789
    ResourceMark rm;
790
    log_info(cds, heap)("Verify heap %s initializing static field(s) in %s",
791
                        which, k->external_name());
792

793
    VM_Verify verify_op;
794
    VMThread::execute(&verify_op);
795

796
    if (VerifyArchivedFields > 1 && is_init_completed()) {
797
      // At this time, the oop->klass() of some archived objects in the heap may not
798
      // have been loaded into the system dictionary yet. Nevertheless, oop->klass() should
799
      // have enough information (object size, oop maps, etc) so that a GC can be safely
800
      // performed.
801
      //
802
      // -XX:VerifyArchivedFields=2 force a GC to happen in such an early stage
803
      // to check for GC safety.
804
      log_info(cds, heap)("Trigger GC %s initializing static field(s) in %s",
805
                          which, k->external_name());
806
      FlagSetting fs1(VerifyBeforeGC, true);
807
      FlagSetting fs2(VerifyDuringGC, true);
808
      FlagSetting fs3(VerifyAfterGC,  true);
809
      Universe::heap()->collect(GCCause::_java_lang_system_gc);
810
    }
811
  }
812
}
813

814
// Before GC can execute, we must ensure that all oops reachable from HeapShared::roots()
815
// have a valid klass. I.e., oopDesc::klass() must have already been resolved.
816
//
817
// Note: if a ArchivedKlassSubGraphInfoRecord contains non-early classes, and JVMTI
818
// ClassFileLoadHook is enabled, it's possible for this class to be dynamically replaced. In
819
// this case, we will not load the ArchivedKlassSubGraphInfoRecord and will clear its roots.
820
void HeapShared::resolve_classes(JavaThread* current) {
821
  assert(CDSConfig::is_using_archive(), "runtime only!");
822
  if (!ArchiveHeapLoader::is_in_use()) {
823
    return; // nothing to do
824
  }
825
  resolve_classes_for_subgraphs(current, archive_subgraph_entry_fields);
826
  resolve_classes_for_subgraphs(current, fmg_archive_subgraph_entry_fields);
827
}
828

829
void HeapShared::resolve_classes_for_subgraphs(JavaThread* current, ArchivableStaticFieldInfo fields[]) {
830
  for (int i = 0; fields[i].valid(); i++) {
831
    ArchivableStaticFieldInfo* info = &fields[i];
832
    TempNewSymbol klass_name = SymbolTable::new_symbol(info->klass_name);
833
    InstanceKlass* k = SystemDictionaryShared::find_builtin_class(klass_name);
834
    assert(k != nullptr && k->is_shared_boot_class(), "sanity");
835
    resolve_classes_for_subgraph_of(current, k);
836
  }
837
}
838

839
void HeapShared::resolve_classes_for_subgraph_of(JavaThread* current, Klass* k) {
840
  JavaThread* THREAD = current;
841
  ExceptionMark em(THREAD);
842
  const ArchivedKlassSubGraphInfoRecord* record =
843
   resolve_or_init_classes_for_subgraph_of(k, /*do_init=*/false, THREAD);
844
  if (HAS_PENDING_EXCEPTION) {
845
   CLEAR_PENDING_EXCEPTION;
846
  }
847
  if (record == nullptr) {
848
   clear_archived_roots_of(k);
849
  }
850
}
851

852
void HeapShared::initialize_from_archived_subgraph(JavaThread* current, Klass* k) {
853
  JavaThread* THREAD = current;
854
  if (!ArchiveHeapLoader::is_in_use()) {
855
    return; // nothing to do
856
  }
857

858
  ExceptionMark em(THREAD);
859
  const ArchivedKlassSubGraphInfoRecord* record =
860
    resolve_or_init_classes_for_subgraph_of(k, /*do_init=*/true, THREAD);
861

862
  if (HAS_PENDING_EXCEPTION) {
863
    CLEAR_PENDING_EXCEPTION;
864
    // None of the field value will be set if there was an exception when initializing the classes.
865
    // The java code will not see any of the archived objects in the
866
    // subgraphs referenced from k in this case.
867
    return;
868
  }
869

870
  if (record != nullptr) {
871
    init_archived_fields_for(k, record);
872
  }
873
}
874

875
const ArchivedKlassSubGraphInfoRecord*
876
HeapShared::resolve_or_init_classes_for_subgraph_of(Klass* k, bool do_init, TRAPS) {
877
  assert(!CDSConfig::is_dumping_heap(), "Should not be called when dumping heap");
878

879
  if (!k->is_shared()) {
880
    return nullptr;
881
  }
882
  unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary_quick(k);
883
  const ArchivedKlassSubGraphInfoRecord* record = _run_time_subgraph_info_table.lookup(k, hash, 0);
884

885
#ifndef PRODUCT
886
  if (_test_class_name != nullptr && k->name()->equals(_test_class_name) && record != nullptr) {
887
    _test_class = k;
888
    _test_class_record = record;
889
  }
890
#endif
891

892
  // Initialize from archived data. Currently this is done only
893
  // during VM initialization time. No lock is needed.
894
  if (record == nullptr) {
895
    if (log_is_enabled(Info, cds, heap)) {
896
      ResourceMark rm(THREAD);
897
      log_info(cds, heap)("subgraph %s is not recorded",
898
                          k->external_name());
899
    }
900
    return nullptr;
901
  } else {
902
    if (record->is_full_module_graph() && !CDSConfig::is_using_full_module_graph()) {
903
      if (log_is_enabled(Info, cds, heap)) {
904
        ResourceMark rm(THREAD);
905
        log_info(cds, heap)("subgraph %s cannot be used because full module graph is disabled",
906
                            k->external_name());
907
      }
908
      return nullptr;
909
    }
910

911
    if (record->has_non_early_klasses() && JvmtiExport::should_post_class_file_load_hook()) {
912
      if (log_is_enabled(Info, cds, heap)) {
913
        ResourceMark rm(THREAD);
914
        log_info(cds, heap)("subgraph %s cannot be used because JVMTI ClassFileLoadHook is enabled",
915
                            k->external_name());
916
      }
917
      return nullptr;
918
    }
919

920
    if (log_is_enabled(Info, cds, heap)) {
921
      ResourceMark rm;
922
      log_info(cds, heap)("%s subgraph %s ", do_init ? "init" : "resolve", k->external_name());
923
    }
924

925
    resolve_or_init(k, do_init, CHECK_NULL);
926

927
    // Load/link/initialize the klasses of the objects in the subgraph.
928
    // nullptr class loader is used.
929
    Array<Klass*>* klasses = record->subgraph_object_klasses();
930
    if (klasses != nullptr) {
931
      for (int i = 0; i < klasses->length(); i++) {
932
        Klass* klass = klasses->at(i);
933
        if (!klass->is_shared()) {
934
          return nullptr;
935
        }
936
        resolve_or_init(klass, do_init, CHECK_NULL);
937
      }
938
    }
939
  }
940

941
  return record;
942
}
943

944
void HeapShared::resolve_or_init(Klass* k, bool do_init, TRAPS) {
945
  if (!do_init) {
946
    if (k->class_loader_data() == nullptr) {
947
      Klass* resolved_k = SystemDictionary::resolve_or_null(k->name(), CHECK);
948
      assert(resolved_k == k, "classes used by archived heap must not be replaced by JVMTI ClassFileLoadHook");
949
    }
950
  } else {
951
    assert(k->class_loader_data() != nullptr, "must have been resolved by HeapShared::resolve_classes");
952
    if (k->is_instance_klass()) {
953
      InstanceKlass* ik = InstanceKlass::cast(k);
954
      ik->initialize(CHECK);
955
    } else if (k->is_objArray_klass()) {
956
      ObjArrayKlass* oak = ObjArrayKlass::cast(k);
957
      oak->initialize(CHECK);
958
    }
959
  }
960
}
961

962
void HeapShared::init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphInfoRecord* record) {
963
  verify_the_heap(k, "before");
964

965
  // Load the subgraph entry fields from the record and store them back to
966
  // the corresponding fields within the mirror.
967
  oop m = k->java_mirror();
968
  Array<int>* entry_field_records = record->entry_field_records();
969
  if (entry_field_records != nullptr) {
970
    int efr_len = entry_field_records->length();
971
    assert(efr_len % 2 == 0, "sanity");
972
    for (int i = 0; i < efr_len; i += 2) {
973
      int field_offset = entry_field_records->at(i);
974
      int root_index = entry_field_records->at(i+1);
975
      oop v = get_root(root_index, /*clear=*/true);
976
      m->obj_field_put(field_offset, v);
977
      log_debug(cds, heap)("  " PTR_FORMAT " init field @ %2d = " PTR_FORMAT, p2i(k), field_offset, p2i(v));
978
    }
979

980
    // Done. Java code can see the archived sub-graphs referenced from k's
981
    // mirror after this point.
982
    if (log_is_enabled(Info, cds, heap)) {
983
      ResourceMark rm;
984
      log_info(cds, heap)("initialize_from_archived_subgraph %s " PTR_FORMAT "%s",
985
                          k->external_name(), p2i(k), JvmtiExport::is_early_phase() ? " (early)" : "");
986
    }
987
  }
988

989
  verify_the_heap(k, "after ");
990
}
991

992
void HeapShared::clear_archived_roots_of(Klass* k) {
993
  unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary_quick(k);
994
  const ArchivedKlassSubGraphInfoRecord* record = _run_time_subgraph_info_table.lookup(k, hash, 0);
995
  if (record != nullptr) {
996
    Array<int>* entry_field_records = record->entry_field_records();
997
    if (entry_field_records != nullptr) {
998
      int efr_len = entry_field_records->length();
999
      assert(efr_len % 2 == 0, "sanity");
1000
      for (int i = 0; i < efr_len; i += 2) {
1001
        int root_index = entry_field_records->at(i+1);
1002
        clear_root(root_index);
1003
      }
1004
    }
1005
  }
1006
}
1007

1008
class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
1009
  int _level;
1010
  bool _record_klasses_only;
1011
  KlassSubGraphInfo* _subgraph_info;
1012
  oop _referencing_obj;
1013

1014
  // The following are for maintaining a stack for determining
1015
  // CachedOopInfo::_referrer
1016
  static WalkOopAndArchiveClosure* _current;
1017
  WalkOopAndArchiveClosure* _last;
1018
 public:
1019
  WalkOopAndArchiveClosure(int level,
1020
                           bool record_klasses_only,
1021
                           KlassSubGraphInfo* subgraph_info,
1022
                           oop orig) :
1023
    _level(level),
1024
    _record_klasses_only(record_klasses_only),
1025
    _subgraph_info(subgraph_info),
1026
    _referencing_obj(orig) {
1027
    _last = _current;
1028
    _current = this;
1029
  }
1030
  ~WalkOopAndArchiveClosure() {
1031
    _current = _last;
1032
  }
1033
  void do_oop(narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }
1034
  void do_oop(      oop *p) { WalkOopAndArchiveClosure::do_oop_work(p); }
1035

1036
 protected:
1037
  template <class T> void do_oop_work(T *p) {
1038
    oop obj = RawAccess<>::oop_load(p);
1039
    if (!CompressedOops::is_null(obj)) {
1040
      size_t field_delta = pointer_delta(p, _referencing_obj, sizeof(char));
1041

1042
      if (!_record_klasses_only && log_is_enabled(Debug, cds, heap)) {
1043
        ResourceMark rm;
1044
        log_debug(cds, heap)("(%d) %s[" SIZE_FORMAT "] ==> " PTR_FORMAT " size " SIZE_FORMAT " %s", _level,
1045
                             _referencing_obj->klass()->external_name(), field_delta,
1046
                             p2i(obj), obj->size() * HeapWordSize, obj->klass()->external_name());
1047
        if (log_is_enabled(Trace, cds, heap)) {
1048
          LogTarget(Trace, cds, heap) log;
1049
          LogStream out(log);
1050
          obj->print_on(&out);
1051
        }
1052
      }
1053

1054
      bool success = HeapShared::archive_reachable_objects_from(
1055
          _level + 1, _subgraph_info, obj);
1056
      assert(success, "VM should have exited with unarchivable objects for _level > 1");
1057
    }
1058
  }
1059

1060
 public:
1061
  static WalkOopAndArchiveClosure* current()  { return _current;              }
1062
  oop referencing_obj()                       { return _referencing_obj;      }
1063
  KlassSubGraphInfo* subgraph_info()          { return _subgraph_info;        }
1064
};
1065

1066
WalkOopAndArchiveClosure* WalkOopAndArchiveClosure::_current = nullptr;
1067

1068
// Checks if an oop has any non-null oop fields
1069
class PointsToOopsChecker : public BasicOopIterateClosure {
1070
  bool _result;
1071

1072
  template <class T> void check(T *p) {
1073
    _result |= (HeapAccess<>::oop_load(p) != nullptr);
1074
  }
1075

1076
public:
1077
  PointsToOopsChecker() : _result(false) {}
1078
  void do_oop(narrowOop *p) { check(p); }
1079
  void do_oop(      oop *p) { check(p); }
1080
  bool result() { return _result; }
1081
};
1082

1083
HeapShared::CachedOopInfo HeapShared::make_cached_oop_info(oop obj) {
1084
  WalkOopAndArchiveClosure* walker = WalkOopAndArchiveClosure::current();
1085
  oop referrer = (walker == nullptr) ? nullptr : walker->referencing_obj();
1086
  PointsToOopsChecker points_to_oops_checker;
1087
  obj->oop_iterate(&points_to_oops_checker);
1088
  return CachedOopInfo(referrer, points_to_oops_checker.result());
1089
}
1090

1091
// (1) If orig_obj has not been archived yet, archive it.
1092
// (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called),
1093
//     trace all  objects that are reachable from it, and make sure these objects are archived.
1094
// (3) Record the klasses of all orig_obj and all reachable objects.
1095
bool HeapShared::archive_reachable_objects_from(int level,
1096
                                                KlassSubGraphInfo* subgraph_info,
1097
                                                oop orig_obj) {
1098
  assert(orig_obj != nullptr, "must be");
1099

1100
  if (!JavaClasses::is_supported_for_archiving(orig_obj)) {
1101
    // This object has injected fields that cannot be supported easily, so we disallow them for now.
1102
    // If you get an error here, you probably made a change in the JDK library that has added
1103
    // these objects that are referenced (directly or indirectly) by static fields.
1104
    ResourceMark rm;
1105
    log_error(cds, heap)("Cannot archive object of class %s", orig_obj->klass()->external_name());
1106
    MetaspaceShared::unrecoverable_writing_error();
1107
  }
1108

1109
  // java.lang.Class instances cannot be included in an archived object sub-graph. We only support
1110
  // them as Klass::_archived_mirror because they need to be specially restored at run time.
1111
  //
1112
  // If you get an error here, you probably made a change in the JDK library that has added a Class
1113
  // object that is referenced (directly or indirectly) by static fields.
1114
  if (java_lang_Class::is_instance(orig_obj) && subgraph_info != _default_subgraph_info) {
1115
    log_error(cds, heap)("(%d) Unknown java.lang.Class object is in the archived sub-graph", level);
1116
    MetaspaceShared::unrecoverable_writing_error();
1117
  }
1118

1119
  if (has_been_seen_during_subgraph_recording(orig_obj)) {
1120
    // orig_obj has already been archived and traced. Nothing more to do.
1121
    return true;
1122
  } else {
1123
    set_has_been_seen_during_subgraph_recording(orig_obj);
1124
  }
1125

1126
  bool already_archived = has_been_archived(orig_obj);
1127
  bool record_klasses_only = already_archived;
1128
  if (!already_archived) {
1129
    ++_num_new_archived_objs;
1130
    if (!archive_object(orig_obj)) {
1131
      // Skip archiving the sub-graph referenced from the current entry field.
1132
      ResourceMark rm;
1133
      log_error(cds, heap)(
1134
        "Cannot archive the sub-graph referenced from %s object ("
1135
        PTR_FORMAT ") size " SIZE_FORMAT ", skipped.",
1136
        orig_obj->klass()->external_name(), p2i(orig_obj), orig_obj->size() * HeapWordSize);
1137
      if (level == 1) {
1138
        // Don't archive a subgraph root that's too big. For archives static fields, that's OK
1139
        // as the Java code will take care of initializing this field dynamically.
1140
        return false;
1141
      } else {
1142
        // We don't know how to handle an object that has been archived, but some of its reachable
1143
        // objects cannot be archived. Bail out for now. We might need to fix this in the future if
1144
        // we have a real use case.
1145
        MetaspaceShared::unrecoverable_writing_error();
1146
      }
1147
    }
1148
  }
1149

1150
  Klass *orig_k = orig_obj->klass();
1151
  subgraph_info->add_subgraph_object_klass(orig_k);
1152

1153
  WalkOopAndArchiveClosure walker(level, record_klasses_only, subgraph_info, orig_obj);
1154
  orig_obj->oop_iterate(&walker);
1155

1156
  if (CDSEnumKlass::is_enum_obj(orig_obj)) {
1157
    CDSEnumKlass::handle_enum_obj(level + 1, subgraph_info, orig_obj);
1158
  }
1159
  return true;
1160
}
1161

1162
//
1163
// Start from the given static field in a java mirror and archive the
1164
// complete sub-graph of java heap objects that are reached directly
1165
// or indirectly from the starting object by following references.
1166
// Sub-graph archiving restrictions (current):
1167
//
1168
// - All classes of objects in the archived sub-graph (including the
1169
//   entry class) must be boot class only.
1170
// - No java.lang.Class instance (java mirror) can be included inside
1171
//   an archived sub-graph. Mirror can only be the sub-graph entry object.
1172
//
1173
// The Java heap object sub-graph archiving process (see
1174
// WalkOopAndArchiveClosure):
1175
//
1176
// 1) Java object sub-graph archiving starts from a given static field
1177
// within a Class instance (java mirror). If the static field is a
1178
// reference field and points to a non-null java object, proceed to
1179
// the next step.
1180
//
1181
// 2) Archives the referenced java object. If an archived copy of the
1182
// current object already exists, updates the pointer in the archived
1183
// copy of the referencing object to point to the current archived object.
1184
// Otherwise, proceed to the next step.
1185
//
1186
// 3) Follows all references within the current java object and recursively
1187
// archive the sub-graph of objects starting from each reference.
1188
//
1189
// 4) Updates the pointer in the archived copy of referencing object to
1190
// point to the current archived object.
1191
//
1192
// 5) The Klass of the current java object is added to the list of Klasses
1193
// for loading and initializing before any object in the archived graph can
1194
// be accessed at runtime.
1195
//
1196
void HeapShared::archive_reachable_objects_from_static_field(InstanceKlass *k,
1197
                                                             const char* klass_name,
1198
                                                             int field_offset,
1199
                                                             const char* field_name) {
1200
  assert(CDSConfig::is_dumping_heap(), "dump time only");
1201
  assert(k->is_shared_boot_class(), "must be boot class");
1202

1203
  oop m = k->java_mirror();
1204

1205
  KlassSubGraphInfo* subgraph_info = get_subgraph_info(k);
1206
  oop f = m->obj_field(field_offset);
1207

1208
  log_debug(cds, heap)("Start archiving from: %s::%s (" PTR_FORMAT ")", klass_name, field_name, p2i(f));
1209

1210
  if (!CompressedOops::is_null(f)) {
1211
    if (log_is_enabled(Trace, cds, heap)) {
1212
      LogTarget(Trace, cds, heap) log;
1213
      LogStream out(log);
1214
      f->print_on(&out);
1215
    }
1216

1217
    bool success = archive_reachable_objects_from(1, subgraph_info, f);
1218
    if (!success) {
1219
      log_error(cds, heap)("Archiving failed %s::%s (some reachable objects cannot be archived)",
1220
                           klass_name, field_name);
1221
    } else {
1222
      // Note: the field value is not preserved in the archived mirror.
1223
      // Record the field as a new subGraph entry point. The recorded
1224
      // information is restored from the archive at runtime.
1225
      subgraph_info->add_subgraph_entry_field(field_offset, f);
1226
      log_info(cds, heap)("Archived field %s::%s => " PTR_FORMAT, klass_name, field_name, p2i(f));
1227
    }
1228
  } else {
1229
    // The field contains null, we still need to record the entry point,
1230
    // so it can be restored at runtime.
1231
    subgraph_info->add_subgraph_entry_field(field_offset, nullptr);
1232
  }
1233
}
1234

1235
#ifndef PRODUCT
1236
class VerifySharedOopClosure: public BasicOopIterateClosure {
1237
 public:
1238
  void do_oop(narrowOop *p) { VerifySharedOopClosure::do_oop_work(p); }
1239
  void do_oop(      oop *p) { VerifySharedOopClosure::do_oop_work(p); }
1240

1241
 protected:
1242
  template <class T> void do_oop_work(T *p) {
1243
    oop obj = RawAccess<>::oop_load(p);
1244
    if (!CompressedOops::is_null(obj)) {
1245
      HeapShared::verify_reachable_objects_from(obj);
1246
    }
1247
  }
1248
};
1249

1250
void HeapShared::verify_subgraph_from_static_field(InstanceKlass* k, int field_offset) {
1251
  assert(CDSConfig::is_dumping_heap(), "dump time only");
1252
  assert(k->is_shared_boot_class(), "must be boot class");
1253

1254
  oop m = k->java_mirror();
1255
  oop f = m->obj_field(field_offset);
1256
  if (!CompressedOops::is_null(f)) {
1257
    verify_subgraph_from(f);
1258
  }
1259
}
1260

1261
void HeapShared::verify_subgraph_from(oop orig_obj) {
1262
  if (!has_been_archived(orig_obj)) {
1263
    // It's OK for the root of a subgraph to be not archived. See comments in
1264
    // archive_reachable_objects_from().
1265
    return;
1266
  }
1267

1268
  // Verify that all objects reachable from orig_obj are archived.
1269
  init_seen_objects_table();
1270
  verify_reachable_objects_from(orig_obj);
1271
  delete_seen_objects_table();
1272
}
1273

1274
void HeapShared::verify_reachable_objects_from(oop obj) {
1275
  _num_total_verifications ++;
1276
  if (!has_been_seen_during_subgraph_recording(obj)) {
1277
    set_has_been_seen_during_subgraph_recording(obj);
1278
    assert(has_been_archived(obj), "must be");
1279
    VerifySharedOopClosure walker;
1280
    obj->oop_iterate(&walker);
1281
  }
1282
}
1283
#endif
1284

1285
// The "default subgraph" contains special objects (see heapShared.hpp) that
1286
// can be accessed before we load any Java classes (including java/lang/Class).
1287
// Make sure that these are only instances of the very few specific types
1288
// that we can handle.
1289
void HeapShared::check_default_subgraph_classes() {
1290
  GrowableArray<Klass*>* klasses = _default_subgraph_info->subgraph_object_klasses();
1291
  int num = klasses->length();
1292
  for (int i = 0; i < num; i++) {
1293
    Klass* subgraph_k = klasses->at(i);
1294
    if (log_is_enabled(Info, cds, heap)) {
1295
      ResourceMark rm;
1296
      log_info(cds, heap)(
1297
          "Archived object klass (default subgraph %d) => %s",
1298
          i, subgraph_k->external_name());
1299
    }
1300

1301
    Symbol* name = ArchiveBuilder::current()->get_source_addr(subgraph_k->name());
1302
    guarantee(name == vmSymbols::java_lang_Class() ||
1303
              name == vmSymbols::java_lang_String() ||
1304
              name == vmSymbols::java_lang_ArithmeticException() ||
1305
              name == vmSymbols::java_lang_NullPointerException() ||
1306
              name == vmSymbols::java_lang_InternalError() ||
1307
              name == vmSymbols::object_array_signature() ||
1308
              name == vmSymbols::byte_array_signature() ||
1309
              name == vmSymbols::char_array_signature(),
1310
              "default subgraph can have only these objects");
1311
  }
1312
}
1313

1314
HeapShared::SeenObjectsTable* HeapShared::_seen_objects_table = nullptr;
1315
int HeapShared::_num_new_walked_objs;
1316
int HeapShared::_num_new_archived_objs;
1317
int HeapShared::_num_old_recorded_klasses;
1318

1319
int HeapShared::_num_total_subgraph_recordings = 0;
1320
int HeapShared::_num_total_walked_objs = 0;
1321
int HeapShared::_num_total_archived_objs = 0;
1322
int HeapShared::_num_total_recorded_klasses = 0;
1323
int HeapShared::_num_total_verifications = 0;
1324

1325
bool HeapShared::has_been_seen_during_subgraph_recording(oop obj) {
1326
  return _seen_objects_table->get(obj) != nullptr;
1327
}
1328

1329
void HeapShared::set_has_been_seen_during_subgraph_recording(oop obj) {
1330
  assert(!has_been_seen_during_subgraph_recording(obj), "sanity");
1331
  _seen_objects_table->put_when_absent(obj, true);
1332
  _seen_objects_table->maybe_grow();
1333
  ++ _num_new_walked_objs;
1334
}
1335

1336
void HeapShared::start_recording_subgraph(InstanceKlass *k, const char* class_name, bool is_full_module_graph) {
1337
  log_info(cds, heap)("Start recording subgraph(s) for archived fields in %s", class_name);
1338
  init_subgraph_info(k, is_full_module_graph);
1339
  init_seen_objects_table();
1340
  _num_new_walked_objs = 0;
1341
  _num_new_archived_objs = 0;
1342
  _num_old_recorded_klasses = get_subgraph_info(k)->num_subgraph_object_klasses();
1343
}
1344

1345
void HeapShared::done_recording_subgraph(InstanceKlass *k, const char* class_name) {
1346
  int num_new_recorded_klasses = get_subgraph_info(k)->num_subgraph_object_klasses() -
1347
    _num_old_recorded_klasses;
1348
  log_info(cds, heap)("Done recording subgraph(s) for archived fields in %s: "
1349
                      "walked %d objs, archived %d new objs, recorded %d classes",
1350
                      class_name, _num_new_walked_objs, _num_new_archived_objs,
1351
                      num_new_recorded_klasses);
1352

1353
  delete_seen_objects_table();
1354

1355
  _num_total_subgraph_recordings ++;
1356
  _num_total_walked_objs      += _num_new_walked_objs;
1357
  _num_total_archived_objs    += _num_new_archived_objs;
1358
  _num_total_recorded_klasses +=  num_new_recorded_klasses;
1359
}
1360

1361
class ArchivableStaticFieldFinder: public FieldClosure {
1362
  InstanceKlass* _ik;
1363
  Symbol* _field_name;
1364
  bool _found;
1365
  int _offset;
1366
public:
1367
  ArchivableStaticFieldFinder(InstanceKlass* ik, Symbol* field_name) :
1368
    _ik(ik), _field_name(field_name), _found(false), _offset(-1) {}
1369

1370
  virtual void do_field(fieldDescriptor* fd) {
1371
    if (fd->name() == _field_name) {
1372
      assert(!_found, "fields can never be overloaded");
1373
      if (is_reference_type(fd->field_type())) {
1374
        _found = true;
1375
        _offset = fd->offset();
1376
      }
1377
    }
1378
  }
1379
  bool found()     { return _found;  }
1380
  int offset()     { return _offset; }
1381
};
1382

1383
void HeapShared::init_subgraph_entry_fields(ArchivableStaticFieldInfo fields[],
1384
                                            TRAPS) {
1385
  for (int i = 0; fields[i].valid(); i++) {
1386
    ArchivableStaticFieldInfo* info = &fields[i];
1387
    TempNewSymbol klass_name =  SymbolTable::new_symbol(info->klass_name);
1388
    TempNewSymbol field_name =  SymbolTable::new_symbol(info->field_name);
1389
    ResourceMark rm; // for stringStream::as_string() etc.
1390

1391
#ifndef PRODUCT
1392
    bool is_test_class = (ArchiveHeapTestClass != nullptr) && (strcmp(info->klass_name, ArchiveHeapTestClass) == 0);
1393
    const char* test_class_name = ArchiveHeapTestClass;
1394
#else
1395
    bool is_test_class = false;
1396
    const char* test_class_name = ""; // avoid C++ printf checks warnings.
1397
#endif
1398

1399
    if (is_test_class) {
1400
      log_warning(cds)("Loading ArchiveHeapTestClass %s ...", test_class_name);
1401
    }
1402

1403
    Klass* k = SystemDictionary::resolve_or_fail(klass_name, true, THREAD);
1404
    if (HAS_PENDING_EXCEPTION) {
1405
      CLEAR_PENDING_EXCEPTION;
1406
      stringStream st;
1407
      st.print("Fail to initialize archive heap: %s cannot be loaded by the boot loader", info->klass_name);
1408
      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), st.as_string());
1409
    }
1410

1411
    if (!k->is_instance_klass()) {
1412
      stringStream st;
1413
      st.print("Fail to initialize archive heap: %s is not an instance class", info->klass_name);
1414
      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), st.as_string());
1415
    }
1416

1417
    InstanceKlass* ik = InstanceKlass::cast(k);
1418
    assert(InstanceKlass::cast(ik)->is_shared_boot_class(),
1419
           "Only support boot classes");
1420

1421
    if (is_test_class) {
1422
      if (ik->module()->is_named()) {
1423
        // We don't want ArchiveHeapTestClass to be abused to easily load/initialize arbitrary
1424
        // core-lib classes. You need to at least append to the bootclasspath.
1425
        stringStream st;
1426
        st.print("ArchiveHeapTestClass %s is not in unnamed module", test_class_name);
1427
        THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), st.as_string());
1428
      }
1429

1430
      if (ik->package() != nullptr) {
1431
        // This restriction makes HeapShared::is_a_test_class_in_unnamed_module() easy.
1432
        stringStream st;
1433
        st.print("ArchiveHeapTestClass %s is not in unnamed package", test_class_name);
1434
        THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), st.as_string());
1435
      }
1436
    } else {
1437
      if (ik->module()->name() != vmSymbols::java_base()) {
1438
        // We don't want to deal with cases when a module is unavailable at runtime.
1439
        // FUTURE -- load from archived heap only when module graph has not changed
1440
        //           between dump and runtime.
1441
        stringStream st;
1442
        st.print("%s is not in java.base module", info->klass_name);
1443
        THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), st.as_string());
1444
      }
1445
    }
1446

1447
    if (is_test_class) {
1448
      log_warning(cds)("Initializing ArchiveHeapTestClass %s ...", test_class_name);
1449
    }
1450
    ik->initialize(CHECK);
1451

1452
    ArchivableStaticFieldFinder finder(ik, field_name);
1453
    ik->do_local_static_fields(&finder);
1454
    if (!finder.found()) {
1455
      stringStream st;
1456
      st.print("Unable to find the static T_OBJECT field %s::%s", info->klass_name, info->field_name);
1457
      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), st.as_string());
1458
    }
1459

1460
    info->klass = ik;
1461
    info->offset = finder.offset();
1462
  }
1463
}
1464

1465
void HeapShared::init_subgraph_entry_fields(TRAPS) {
1466
  assert(HeapShared::can_write(), "must be");
1467
  _dump_time_subgraph_info_table = new (mtClass)DumpTimeKlassSubGraphInfoTable();
1468
  init_subgraph_entry_fields(archive_subgraph_entry_fields, CHECK);
1469
  if (CDSConfig::is_dumping_full_module_graph()) {
1470
    init_subgraph_entry_fields(fmg_archive_subgraph_entry_fields, CHECK);
1471
  }
1472
}
1473

1474
#ifndef PRODUCT
1475
void HeapShared::setup_test_class(const char* test_class_name) {
1476
  ArchivableStaticFieldInfo* p = archive_subgraph_entry_fields;
1477
  int num_slots = sizeof(archive_subgraph_entry_fields) / sizeof(ArchivableStaticFieldInfo);
1478
  assert(p[num_slots - 2].klass_name == nullptr, "must have empty slot that's patched below");
1479
  assert(p[num_slots - 1].klass_name == nullptr, "must have empty slot that marks the end of the list");
1480

1481
  if (test_class_name != nullptr) {
1482
    p[num_slots - 2].klass_name = test_class_name;
1483
    p[num_slots - 2].field_name = ARCHIVE_TEST_FIELD_NAME;
1484
  }
1485
}
1486

1487
// See if ik is one of the test classes that are pulled in by -XX:ArchiveHeapTestClass
1488
// during runtime. This may be called before the module system is initialized so
1489
// we cannot rely on InstanceKlass::module(), etc.
1490
bool HeapShared::is_a_test_class_in_unnamed_module(Klass* ik) {
1491
  if (_test_class != nullptr) {
1492
    if (ik == _test_class) {
1493
      return true;
1494
    }
1495
    Array<Klass*>* klasses = _test_class_record->subgraph_object_klasses();
1496
    if (klasses == nullptr) {
1497
      return false;
1498
    }
1499

1500
    for (int i = 0; i < klasses->length(); i++) {
1501
      Klass* k = klasses->at(i);
1502
      if (k == ik) {
1503
        Symbol* name;
1504
        if (k->is_instance_klass()) {
1505
          name = InstanceKlass::cast(k)->name();
1506
        } else if (k->is_objArray_klass()) {
1507
          Klass* bk = ObjArrayKlass::cast(k)->bottom_klass();
1508
          if (!bk->is_instance_klass()) {
1509
            return false;
1510
          }
1511
          name = bk->name();
1512
        } else {
1513
          return false;
1514
        }
1515

1516
        // See KlassSubGraphInfo::check_allowed_klass() - only two types of
1517
        // classes are allowed:
1518
        //   (A) java.base classes (which must not be in the unnamed module)
1519
        //   (B) test classes which must be in the unnamed package of the unnamed module.
1520
        // So if we see a '/' character in the class name, it must be in (A);
1521
        // otherwise it must be in (B).
1522
        if (name->index_of_at(0, "/", 1)  >= 0) {
1523
          return false; // (A)
1524
        }
1525

1526
        return true; // (B)
1527
      }
1528
    }
1529
  }
1530

1531
  return false;
1532
}
1533
#endif
1534

1535
void HeapShared::init_for_dumping(TRAPS) {
1536
  if (HeapShared::can_write()) {
1537
    setup_test_class(ArchiveHeapTestClass);
1538
    _dumped_interned_strings = new (mtClass)DumpedInternedStrings(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE);
1539
    init_subgraph_entry_fields(CHECK);
1540
  }
1541
}
1542

1543
void HeapShared::archive_object_subgraphs(ArchivableStaticFieldInfo fields[],
1544
                                          bool is_full_module_graph) {
1545
  _num_total_subgraph_recordings = 0;
1546
  _num_total_walked_objs = 0;
1547
  _num_total_archived_objs = 0;
1548
  _num_total_recorded_klasses = 0;
1549
  _num_total_verifications = 0;
1550

1551
  // For each class X that has one or more archived fields:
1552
  // [1] Dump the subgraph of each archived field
1553
  // [2] Create a list of all the class of the objects that can be reached
1554
  //     by any of these static fields.
1555
  //     At runtime, these classes are initialized before X's archived fields
1556
  //     are restored by HeapShared::initialize_from_archived_subgraph().
1557
  int i;
1558
  for (int i = 0; fields[i].valid(); ) {
1559
    ArchivableStaticFieldInfo* info = &fields[i];
1560
    const char* klass_name = info->klass_name;
1561
    start_recording_subgraph(info->klass, klass_name, is_full_module_graph);
1562

1563
    // If you have specified consecutive fields of the same klass in
1564
    // fields[], these will be archived in the same
1565
    // {start_recording_subgraph ... done_recording_subgraph} pass to
1566
    // save time.
1567
    for (; fields[i].valid(); i++) {
1568
      ArchivableStaticFieldInfo* f = &fields[i];
1569
      if (f->klass_name != klass_name) {
1570
        break;
1571
      }
1572

1573
      archive_reachable_objects_from_static_field(f->klass, f->klass_name,
1574
                                                  f->offset, f->field_name);
1575
    }
1576
    done_recording_subgraph(info->klass, klass_name);
1577
  }
1578

1579
  log_info(cds, heap)("Archived subgraph records = %d",
1580
                      _num_total_subgraph_recordings);
1581
  log_info(cds, heap)("  Walked %d objects", _num_total_walked_objs);
1582
  log_info(cds, heap)("  Archived %d objects", _num_total_archived_objs);
1583
  log_info(cds, heap)("  Recorded %d klasses", _num_total_recorded_klasses);
1584

1585
#ifndef PRODUCT
1586
  for (int i = 0; fields[i].valid(); i++) {
1587
    ArchivableStaticFieldInfo* f = &fields[i];
1588
    verify_subgraph_from_static_field(f->klass, f->offset);
1589
  }
1590
  log_info(cds, heap)("  Verified %d references", _num_total_verifications);
1591
#endif
1592
}
1593

1594
// Not all the strings in the global StringTable are dumped into the archive, because
1595
// some of those strings may be only referenced by classes that are excluded from
1596
// the archive. We need to explicitly mark the strings that are:
1597
//   [1] used by classes that WILL be archived;
1598
//   [2] included in the SharedArchiveConfigFile.
1599
void HeapShared::add_to_dumped_interned_strings(oop string) {
1600
  assert_at_safepoint(); // DumpedInternedStrings uses raw oops
1601
  assert(!ArchiveHeapWriter::is_string_too_large_to_archive(string), "must be");
1602
  bool created;
1603
  _dumped_interned_strings->put_if_absent(string, true, &created);
1604
  if (created) {
1605
    _dumped_interned_strings->maybe_grow();
1606
  }
1607
}
1608

1609
#ifndef PRODUCT
1610
// At dump-time, find the location of all the non-null oop pointers in an archived heap
1611
// region. This way we can quickly relocate all the pointers without using
1612
// BasicOopIterateClosure at runtime.
1613
class FindEmbeddedNonNullPointers: public BasicOopIterateClosure {
1614
  void* _start;
1615
  BitMap *_oopmap;
1616
  int _num_total_oops;
1617
  int _num_null_oops;
1618
 public:
1619
  FindEmbeddedNonNullPointers(void* start, BitMap* oopmap)
1620
    : _start(start), _oopmap(oopmap), _num_total_oops(0),  _num_null_oops(0) {}
1621

1622
  virtual void do_oop(narrowOop* p) {
1623
    assert(UseCompressedOops, "sanity");
1624
    _num_total_oops ++;
1625
    narrowOop v = *p;
1626
    if (!CompressedOops::is_null(v)) {
1627
      size_t idx = p - (narrowOop*)_start;
1628
      _oopmap->set_bit(idx);
1629
    } else {
1630
      _num_null_oops ++;
1631
    }
1632
  }
1633
  virtual void do_oop(oop* p) {
1634
    assert(!UseCompressedOops, "sanity");
1635
    _num_total_oops ++;
1636
    if ((*p) != nullptr) {
1637
      size_t idx = p - (oop*)_start;
1638
      _oopmap->set_bit(idx);
1639
    } else {
1640
      _num_null_oops ++;
1641
    }
1642
  }
1643
  int num_total_oops() const { return _num_total_oops; }
1644
  int num_null_oops()  const { return _num_null_oops; }
1645
};
1646
#endif
1647

1648
#ifndef PRODUCT
1649
ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) {
1650
  size_t num_bits = region.byte_size() / (UseCompressedOops ? sizeof(narrowOop) : sizeof(oop));
1651
  ResourceBitMap oopmap(num_bits);
1652

1653
  HeapWord* p   = region.start();
1654
  HeapWord* end = region.end();
1655
  FindEmbeddedNonNullPointers finder((void*)p, &oopmap);
1656

1657
  int num_objs = 0;
1658
  while (p < end) {
1659
    oop o = cast_to_oop(p);
1660
    o->oop_iterate(&finder);
1661
    p += o->size();
1662
    ++ num_objs;
1663
  }
1664

1665
  log_info(cds, heap)("calculate_oopmap: objects = %6d, oop fields = %7d (nulls = %7d)",
1666
                      num_objs, finder.num_total_oops(), finder.num_null_oops());
1667
  return oopmap;
1668
}
1669

1670
#endif // !PRODUCT
1671

1672
void HeapShared::count_allocation(size_t size) {
1673
  _total_obj_count ++;
1674
  _total_obj_size += size;
1675
  for (int i = 0; i < ALLOC_STAT_SLOTS; i++) {
1676
    if (size <= (size_t(1) << i)) {
1677
      _alloc_count[i] ++;
1678
      _alloc_size[i] += size;
1679
      return;
1680
    }
1681
  }
1682
}
1683

1684
static double avg_size(size_t size, size_t count) {
1685
  double avg = 0;
1686
  if (count > 0) {
1687
    avg = double(size * HeapWordSize) / double(count);
1688
  }
1689
  return avg;
1690
}
1691

1692
void HeapShared::print_stats() {
1693
  size_t huge_count = _total_obj_count;
1694
  size_t huge_size = _total_obj_size;
1695

1696
  for (int i = 0; i < ALLOC_STAT_SLOTS; i++) {
1697
    size_t byte_size_limit = (size_t(1) << i) * HeapWordSize;
1698
    size_t count = _alloc_count[i];
1699
    size_t size = _alloc_size[i];
1700
    log_info(cds, heap)(SIZE_FORMAT_W(8) " objects are <= " SIZE_FORMAT_W(-6)
1701
                        " bytes (total " SIZE_FORMAT_W(8) " bytes, avg %8.1f bytes)",
1702
                        count, byte_size_limit, size * HeapWordSize, avg_size(size, count));
1703
    huge_count -= count;
1704
    huge_size -= size;
1705
  }
1706

1707
  log_info(cds, heap)(SIZE_FORMAT_W(8) " huge  objects               (total "  SIZE_FORMAT_W(8) " bytes"
1708
                      ", avg %8.1f bytes)",
1709
                      huge_count, huge_size * HeapWordSize,
1710
                      avg_size(huge_size, huge_count));
1711
  log_info(cds, heap)(SIZE_FORMAT_W(8) " total objects               (total "  SIZE_FORMAT_W(8) " bytes"
1712
                      ", avg %8.1f bytes)",
1713
                      _total_obj_count, _total_obj_size * HeapWordSize,
1714
                      avg_size(_total_obj_size, _total_obj_count));
1715
}
1716

1717
bool HeapShared::is_archived_boot_layer_available(JavaThread* current) {
1718
  TempNewSymbol klass_name = SymbolTable::new_symbol(ARCHIVED_BOOT_LAYER_CLASS);
1719
  InstanceKlass* k = SystemDictionary::find_instance_klass(current, klass_name, Handle(), Handle());
1720
  if (k == nullptr) {
1721
    return false;
1722
  } else {
1723
    TempNewSymbol field_name = SymbolTable::new_symbol(ARCHIVED_BOOT_LAYER_FIELD);
1724
    TempNewSymbol field_signature = SymbolTable::new_symbol("Ljdk/internal/module/ArchivedBootLayer;");
1725
    fieldDescriptor fd;
1726
    if (k->find_field(field_name, field_signature, true, &fd) != nullptr) {
1727
      oop m = k->java_mirror();
1728
      oop f = m->obj_field(fd.offset());
1729
      if (CompressedOops::is_null(f)) {
1730
        return false;
1731
      }
1732
    } else {
1733
      return false;
1734
    }
1735
  }
1736
  return true;
1737
}
1738

1739
#endif // INCLUDE_CDS_JAVA_HEAP
1740

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.