8344913: Improve -Xlog:cds+map+oop logging for Java mirrors
Reviewed-by: dholmes, ccheung
This commit is contained in:
parent
cf5ee0bda2
commit
f51363e027
@ -1294,10 +1294,15 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
|
|||||||
|
|
||||||
if (source_oop != nullptr) {
|
if (source_oop != nullptr) {
|
||||||
// This is a regular oop that got archived.
|
// This is a regular oop that got archived.
|
||||||
print_oop_with_requested_addr_cr(&st, source_oop, false);
|
// Don't print the requested addr again as we have just printed it at the beginning of the line.
|
||||||
|
// Example:
|
||||||
|
// 0x00000007ffd27938: @@ Object (0xfffa4f27) java.util.HashMap
|
||||||
|
print_oop_info_cr(&st, source_oop, /*print_requested_addr=*/false);
|
||||||
byte_size = source_oop->size() * BytesPerWord;
|
byte_size = source_oop->size() * BytesPerWord;
|
||||||
} else if ((byte_size = ArchiveHeapWriter::get_filler_size_at(start)) > 0) {
|
} else if ((byte_size = ArchiveHeapWriter::get_filler_size_at(start)) > 0) {
|
||||||
// We have a filler oop, which also does not exist in BufferOffsetToSourceObjectTable.
|
// We have a filler oop, which also does not exist in BufferOffsetToSourceObjectTable.
|
||||||
|
// Example:
|
||||||
|
// 0x00000007ffc3ffd8: @@ Object filler 40 bytes
|
||||||
st.print_cr("filler " SIZE_FORMAT " bytes", byte_size);
|
st.print_cr("filler " SIZE_FORMAT " bytes", byte_size);
|
||||||
} else {
|
} else {
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
@ -1315,7 +1320,7 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
|
|||||||
|
|
||||||
// ArchivedFieldPrinter is used to print the fields of archived objects. We can't
|
// ArchivedFieldPrinter is used to print the fields of archived objects. We can't
|
||||||
// use _source_obj->print_on(), because we want to print the oop fields
|
// use _source_obj->print_on(), because we want to print the oop fields
|
||||||
// in _source_obj with their requested addresses using print_oop_with_requested_addr_cr().
|
// in _source_obj with their requested addresses using print_oop_info_cr().
|
||||||
class ArchivedFieldPrinter : public FieldClosure {
|
class ArchivedFieldPrinter : public FieldClosure {
|
||||||
ArchiveHeapInfo* _heap_info;
|
ArchiveHeapInfo* _heap_info;
|
||||||
outputStream* _st;
|
outputStream* _st;
|
||||||
@ -1331,8 +1336,14 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
|
|||||||
switch (ft) {
|
switch (ft) {
|
||||||
case T_ARRAY:
|
case T_ARRAY:
|
||||||
case T_OBJECT:
|
case T_OBJECT:
|
||||||
fd->print_on(_st); // print just the name and offset
|
{
|
||||||
print_oop_with_requested_addr_cr(_st, _source_obj->obj_field(fd->offset()));
|
fd->print_on(_st); // print just the name and offset
|
||||||
|
oop obj = _source_obj->obj_field(fd->offset());
|
||||||
|
if (java_lang_Class::is_instance(obj)) {
|
||||||
|
obj = HeapShared::scratch_java_mirror(obj);
|
||||||
|
}
|
||||||
|
print_oop_info_cr(_st, obj);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (ArchiveHeapWriter::is_marked_as_native_pointer(_heap_info, _source_obj, fd->offset())) {
|
if (ArchiveHeapWriter::is_marked_as_native_pointer(_heap_info, _source_obj, fd->offset())) {
|
||||||
@ -1388,37 +1399,78 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
|
|||||||
objArrayOop source_obj_array = objArrayOop(source_oop);
|
objArrayOop source_obj_array = objArrayOop(source_oop);
|
||||||
for (int i = 0; i < source_obj_array->length(); i++) {
|
for (int i = 0; i < source_obj_array->length(); i++) {
|
||||||
st.print(" -%4d: ", i);
|
st.print(" -%4d: ", i);
|
||||||
print_oop_with_requested_addr_cr(&st, source_obj_array->obj_at(i));
|
oop obj = source_obj_array->obj_at(i);
|
||||||
|
if (java_lang_Class::is_instance(obj)) {
|
||||||
|
obj = HeapShared::scratch_java_mirror(obj);
|
||||||
|
}
|
||||||
|
print_oop_info_cr(&st, obj);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
st.print_cr(" - fields (" SIZE_FORMAT " words):", source_oop->size());
|
st.print_cr(" - fields (" SIZE_FORMAT " words):", source_oop->size());
|
||||||
ArchivedFieldPrinter print_field(heap_info, &st, source_oop, buffered_addr);
|
ArchivedFieldPrinter print_field(heap_info, &st, source_oop, buffered_addr);
|
||||||
InstanceKlass::cast(source_klass)->print_nonstatic_fields(&print_field);
|
InstanceKlass::cast(source_klass)->print_nonstatic_fields(&print_field);
|
||||||
|
|
||||||
|
if (java_lang_Class::is_instance(source_oop)) {
|
||||||
|
oop scratch_mirror = source_oop;
|
||||||
|
st.print(" - signature: ");
|
||||||
|
print_class_signature_for_mirror(&st, scratch_mirror);
|
||||||
|
st.cr();
|
||||||
|
|
||||||
|
Klass* src_klass = java_lang_Class::as_Klass(scratch_mirror);
|
||||||
|
if (src_klass != nullptr && src_klass->is_instance_klass()) {
|
||||||
|
oop rr = HeapShared::scratch_resolved_references(InstanceKlass::cast(src_klass)->constants());
|
||||||
|
st.print(" - archived_resolved_references: ");
|
||||||
|
print_oop_info_cr(&st, rr);
|
||||||
|
|
||||||
|
// We need to print the fields in the scratch_mirror, not the original mirror.
|
||||||
|
// (if a class is not aot-initialized, static fields in its scratch mirror will be cleared).
|
||||||
|
assert(scratch_mirror == HeapShared::scratch_java_mirror(src_klass->java_mirror()), "sanity");
|
||||||
|
st.print_cr("- ---- static fields (%d):", java_lang_Class::static_oop_field_count(scratch_mirror));
|
||||||
|
InstanceKlass::cast(src_klass)->do_local_static_fields(&print_field);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print_class_signature_for_mirror(outputStream* st, oop scratch_mirror) {
|
||||||
|
assert(java_lang_Class::is_instance(scratch_mirror), "sanity");
|
||||||
|
if (java_lang_Class::is_primitive(scratch_mirror)) {
|
||||||
|
for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
|
||||||
|
BasicType bt = (BasicType)i;
|
||||||
|
if (!is_reference_type(bt) && scratch_mirror == HeapShared::scratch_java_mirror(bt)) {
|
||||||
|
oop orig_mirror = Universe::java_mirror(bt);
|
||||||
|
java_lang_Class::print_signature(orig_mirror, st);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
java_lang_Class::print_signature(scratch_mirror, st);
|
||||||
|
}
|
||||||
|
|
||||||
static void log_heap_roots() {
|
static void log_heap_roots() {
|
||||||
LogStreamHandle(Trace, cds, map, oops) st;
|
LogStreamHandle(Trace, cds, map, oops) st;
|
||||||
if (st.is_enabled()) {
|
if (st.is_enabled()) {
|
||||||
for (int i = 0; i < HeapShared::pending_roots()->length(); i++) {
|
for (int i = 0; i < HeapShared::pending_roots()->length(); i++) {
|
||||||
st.print("roots[%4d]: ", i);
|
st.print("roots[%4d]: ", i);
|
||||||
print_oop_with_requested_addr_cr(&st, HeapShared::pending_roots()->at(i));
|
print_oop_info_cr(&st, HeapShared::pending_roots()->at(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The output looks like this. The first number is the requested address. The second number is
|
// Example output:
|
||||||
// the narrowOop version of the requested address.
|
// - The first number is the requested address (if print_requested_addr == true)
|
||||||
// 0x00000007ffc7e840 (0xfff8fd08) java.lang.Class
|
// - The second number is the narrowOop version of the requested address (if UseCompressedOops == true)
|
||||||
|
// 0x00000007ffc7e840 (0xfff8fd08) java.lang.Class Ljava/util/Array;
|
||||||
// 0x00000007ffc000f8 (0xfff8001f) [B length: 11
|
// 0x00000007ffc000f8 (0xfff8001f) [B length: 11
|
||||||
static void print_oop_with_requested_addr_cr(outputStream* st, oop source_oop, bool print_addr = true) {
|
static void print_oop_info_cr(outputStream* st, oop source_oop, bool print_requested_addr = true) {
|
||||||
if (source_oop == nullptr) {
|
if (source_oop == nullptr) {
|
||||||
st->print_cr("null");
|
st->print_cr("null");
|
||||||
} else {
|
} else {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
oop requested_obj = ArchiveHeapWriter::source_obj_to_requested_obj(source_oop);
|
oop requested_obj = ArchiveHeapWriter::source_obj_to_requested_obj(source_oop);
|
||||||
if (print_addr) {
|
if (print_requested_addr) {
|
||||||
st->print(PTR_FORMAT " ", p2i(requested_obj));
|
st->print(PTR_FORMAT " ", p2i(requested_obj));
|
||||||
}
|
}
|
||||||
if (UseCompressedOops) {
|
if (UseCompressedOops) {
|
||||||
@ -1428,7 +1480,27 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
|
|||||||
int array_len = arrayOop(source_oop)->length();
|
int array_len = arrayOop(source_oop)->length();
|
||||||
st->print_cr("%s length: %d", source_oop->klass()->external_name(), array_len);
|
st->print_cr("%s length: %d", source_oop->klass()->external_name(), array_len);
|
||||||
} else {
|
} else {
|
||||||
st->print_cr("%s", source_oop->klass()->external_name());
|
st->print("%s", source_oop->klass()->external_name());
|
||||||
|
|
||||||
|
if (java_lang_String::is_instance(source_oop)) {
|
||||||
|
st->print(" ");
|
||||||
|
java_lang_String::print(source_oop, st);
|
||||||
|
} else if (java_lang_Class::is_instance(source_oop)) {
|
||||||
|
oop scratch_mirror = source_oop;
|
||||||
|
|
||||||
|
st->print(" ");
|
||||||
|
print_class_signature_for_mirror(st, scratch_mirror);
|
||||||
|
|
||||||
|
Klass* src_klass = java_lang_Class::as_Klass(scratch_mirror);
|
||||||
|
if (src_klass != nullptr && src_klass->is_instance_klass()) {
|
||||||
|
InstanceKlass* buffered_klass =
|
||||||
|
ArchiveBuilder::current()->get_buffered_addr(InstanceKlass::cast(src_klass));
|
||||||
|
if (buffered_klass->has_aot_initialized_mirror()) {
|
||||||
|
st->print(" (aot-inited)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
st->cr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ This is a simple parser for parsing the output of
|
|||||||
The map file contains patterns like this for the heap objects:
|
The map file contains patterns like this for the heap objects:
|
||||||
|
|
||||||
======================================================================
|
======================================================================
|
||||||
0x00000000ffe00000: @@ Object (0xffe00000) java.lang.String
|
0x00000000ffe00000: @@ Object (0xffe00000) java.lang.String ""
|
||||||
- klass: 'java/lang/String' 0x0000000800010220
|
- klass: 'java/lang/String' 0x0000000800010220
|
||||||
- fields (3 words):
|
- fields (3 words):
|
||||||
- private 'hash' 'I' @12 0 (0x00000000)
|
- private 'hash' 'I' @12 0 (0x00000000)
|
||||||
@ -149,11 +149,11 @@ public class CDSMapReader {
|
|||||||
|
|
||||||
// (one address)
|
// (one address)
|
||||||
// 0x00000007ffc00000: @@ Object java.lang.String
|
// 0x00000007ffc00000: @@ Object java.lang.String
|
||||||
static Pattern objPattern1 = Pattern.compile("^0x([0-9a-f]+): @@ Object (.*)");
|
static Pattern objPattern1 = Pattern.compile("^0x([0-9a-f]+): @@ Object ([^ ]*)");
|
||||||
|
|
||||||
// (two addresses)
|
// (two addresses)
|
||||||
// 0x00000007ffc00000: @@ Object (0xfff80000) java.lang.String
|
// 0x00000007ffc00000: @@ Object (0xfff80000) java.lang.String
|
||||||
static Pattern objPattern2 = Pattern.compile("^0x([0-9a-f]+): @@ Object [(]0x([0-9a-f]+)[)] (.*)");
|
static Pattern objPattern2 = Pattern.compile("^0x([0-9a-f]+): @@ Object [(]0x([0-9a-f]+)[)] ([^ ]*)");
|
||||||
|
|
||||||
// - klass: 'java/lang/String' 0x0000000800010290
|
// - klass: 'java/lang/String' 0x0000000800010290
|
||||||
static Pattern instanceObjKlassPattern = Pattern.compile("^ - klass: '([^']+)' 0x([0-9a-f]+)");
|
static Pattern instanceObjKlassPattern = Pattern.compile("^ - klass: '([^']+)' 0x([0-9a-f]+)");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user