8298524: Debug function to trace reachability of CDS archived heap objects

Reviewed-by: ccheung
This commit is contained in:
Ioi Lam 2022-12-13 19:35:30 +00:00
parent 23e18275ac
commit 68022770de
2 changed files with 29 additions and 19 deletions

View File

@ -236,7 +236,7 @@ inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo&
ls.print("Value: "); ls.print("Value: ");
orig_obj->print_on(&ls); orig_obj->print_on(&ls);
ls.print_cr("--- trace begin ---"); ls.print_cr("--- trace begin ---");
trace_to_root(orig_obj, NULL, &value); trace_to_root(&ls, orig_obj, NULL, &value);
ls.print_cr("--- trace end ---"); ls.print_cr("--- trace end ---");
ls.cr(); ls.cr();
_problems ++; _problems ++;
@ -248,54 +248,62 @@ inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo&
class CDSHeapVerifier::TraceFields : public FieldClosure { class CDSHeapVerifier::TraceFields : public FieldClosure {
oop _orig_obj; oop _orig_obj;
oop _orig_field; oop _orig_field;
LogStream* _ls; outputStream* _st;
public: public:
TraceFields(oop orig_obj, oop orig_field, LogStream* ls) TraceFields(oop orig_obj, oop orig_field, outputStream* st)
: _orig_obj(orig_obj), _orig_field(orig_field), _ls(ls) {} : _orig_obj(orig_obj), _orig_field(orig_field), _st(st) {}
void do_field(fieldDescriptor* fd) { void do_field(fieldDescriptor* fd) {
if (fd->field_type() == T_OBJECT || fd->field_type() == T_ARRAY) { if (fd->field_type() == T_OBJECT || fd->field_type() == T_ARRAY) {
oop obj_field = _orig_obj->obj_field(fd->offset()); oop obj_field = _orig_obj->obj_field(fd->offset());
if (obj_field == _orig_field) { if (obj_field == _orig_field) {
_ls->print("::%s (offset = %d)", fd->name()->as_C_string(), fd->offset()); _st->print("::%s (offset = %d)", fd->name()->as_C_string(), fd->offset());
} }
} }
} }
}; };
// Hint: to exercise this function, uncomment out one of the ADD_EXCL lines above. // Call this function (from gdb, etc) if you want to know why an object is archived.
int CDSHeapVerifier::trace_to_root(oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* p) { void CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj) {
HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache()->get(orig_obj);
if (info != NULL) {
trace_to_root(st, orig_obj, NULL, info);
} else {
st->print_cr("Not an archived object??");
}
}
int CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* info) {
int level = 0; int level = 0;
LogStream ls(Log(cds, heap)::warning()); if (info->_referrer != NULL) {
if (p->_referrer != NULL) { HeapShared::CachedOopInfo* ref = HeapShared::archived_object_cache()->get(info->_referrer);
HeapShared::CachedOopInfo* ref = HeapShared::archived_object_cache()->get(p->_referrer);
assert(ref != NULL, "sanity"); assert(ref != NULL, "sanity");
level = trace_to_root(p->_referrer, orig_obj, ref) + 1; level = trace_to_root(st, info->_referrer, orig_obj, ref) + 1;
} else if (java_lang_String::is_instance(orig_obj)) { } else if (java_lang_String::is_instance(orig_obj)) {
ls.print_cr("[%2d] (shared string table)", level++); st->print_cr("[%2d] (shared string table)", level++);
} }
Klass* k = orig_obj->klass(); Klass* k = orig_obj->klass();
ResourceMark rm; ResourceMark rm;
ls.print("[%2d] ", level); st->print("[%2d] ", level);
orig_obj->print_address_on(&ls); orig_obj->print_address_on(st);
ls.print(" %s", k->internal_name()); st->print(" %s", k->internal_name());
if (orig_field != NULL) { if (orig_field != NULL) {
if (k->is_instance_klass()) { if (k->is_instance_klass()) {
TraceFields clo(orig_obj, orig_field, &ls);; TraceFields clo(orig_obj, orig_field, st);
InstanceKlass::cast(k)->do_nonstatic_fields(&clo); InstanceKlass::cast(k)->do_nonstatic_fields(&clo);
} else { } else {
assert(orig_obj->is_objArray(), "must be"); assert(orig_obj->is_objArray(), "must be");
objArrayOop array = (objArrayOop)orig_obj; objArrayOop array = (objArrayOop)orig_obj;
for (int i = 0; i < array->length(); i++) { for (int i = 0; i < array->length(); i++) {
if (array->obj_at(i) == orig_field) { if (array->obj_at(i) == orig_field) {
ls.print(" @[%d]", i); st->print(" @[%d]", i);
break; break;
} }
} }
} }
} }
ls.cr(); st->cr();
return level; return level;
} }

View File

@ -69,7 +69,7 @@ class CDSHeapVerifier : public KlassClosure {
} }
return NULL; return NULL;
} }
int trace_to_root(oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* p); static int trace_to_root(outputStream* st, oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* p);
CDSHeapVerifier(); CDSHeapVerifier();
~CDSHeapVerifier(); ~CDSHeapVerifier();
@ -83,6 +83,8 @@ public:
inline bool do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value); inline bool do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value);
static void verify() NOT_DEBUG_RETURN; static void verify() NOT_DEBUG_RETURN;
static void trace_to_root(outputStream* st, oop orig_obj);
}; };
#endif // INCLUDE_CDS_JAVA_HEAP #endif // INCLUDE_CDS_JAVA_HEAP