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: ");
orig_obj->print_on(&ls);
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.cr();
_problems ++;
@ -248,54 +248,62 @@ inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo&
class CDSHeapVerifier::TraceFields : public FieldClosure {
oop _orig_obj;
oop _orig_field;
LogStream* _ls;
outputStream* _st;
public:
TraceFields(oop orig_obj, oop orig_field, LogStream* ls)
: _orig_obj(orig_obj), _orig_field(orig_field), _ls(ls) {}
TraceFields(oop orig_obj, oop orig_field, outputStream* st)
: _orig_obj(orig_obj), _orig_field(orig_field), _st(st) {}
void do_field(fieldDescriptor* fd) {
if (fd->field_type() == T_OBJECT || fd->field_type() == T_ARRAY) {
oop obj_field = _orig_obj->obj_field(fd->offset());
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.
int CDSHeapVerifier::trace_to_root(oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* p) {
// Call this function (from gdb, etc) if you want to know why an object is archived.
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;
LogStream ls(Log(cds, heap)::warning());
if (p->_referrer != NULL) {
HeapShared::CachedOopInfo* ref = HeapShared::archived_object_cache()->get(p->_referrer);
if (info->_referrer != NULL) {
HeapShared::CachedOopInfo* ref = HeapShared::archived_object_cache()->get(info->_referrer);
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)) {
ls.print_cr("[%2d] (shared string table)", level++);
st->print_cr("[%2d] (shared string table)", level++);
}
Klass* k = orig_obj->klass();
ResourceMark rm;
ls.print("[%2d] ", level);
orig_obj->print_address_on(&ls);
ls.print(" %s", k->internal_name());
st->print("[%2d] ", level);
orig_obj->print_address_on(st);
st->print(" %s", k->internal_name());
if (orig_field != NULL) {
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);
} else {
assert(orig_obj->is_objArray(), "must be");
objArrayOop array = (objArrayOop)orig_obj;
for (int i = 0; i < array->length(); i++) {
if (array->obj_at(i) == orig_field) {
ls.print(" @[%d]", i);
st->print(" @[%d]", i);
break;
}
}
}
}
ls.cr();
st->cr();
return level;
}

View File

@ -69,7 +69,7 @@ class CDSHeapVerifier : public KlassClosure {
}
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();
@ -83,6 +83,8 @@ public:
inline bool do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value);
static void verify() NOT_DEBUG_RETURN;
static void trace_to_root(outputStream* st, oop orig_obj);
};
#endif // INCLUDE_CDS_JAVA_HEAP