8261269: When using clhsdb to "inspect" a java object, clhsdb prints "Oop for..." twice
Reviewed-by: sspitsyn, kevinw
This commit is contained in:
parent
a7e2e80ff4
commit
aea474c48d
@ -267,34 +267,12 @@ public class CommandProcessor {
|
||||
out.println("Usage: " + usage);
|
||||
}
|
||||
|
||||
void printOopValue(Oop oop) {
|
||||
if (oop != null) {
|
||||
Klass k = oop.getKlass();
|
||||
Symbol s = k.getName();
|
||||
if (s != null) {
|
||||
out.print("Oop for " + s.asString() + " @ ");
|
||||
} else {
|
||||
out.print("Oop @ ");
|
||||
}
|
||||
Oop.printOopAddressOn(oop, out);
|
||||
} else {
|
||||
out.print("null");
|
||||
}
|
||||
}
|
||||
|
||||
void printNode(SimpleTreeNode node) {
|
||||
int count = node.getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
try {
|
||||
SimpleTreeNode field = node.getChild(i);
|
||||
if (field instanceof OopTreeNodeAdapter) {
|
||||
out.print(field);
|
||||
out.print(" ");
|
||||
printOopValue(((OopTreeNodeAdapter)field).getOop());
|
||||
out.println();
|
||||
} else {
|
||||
out.println(field);
|
||||
}
|
||||
out.println(field);
|
||||
} catch (Exception e) {
|
||||
out.println();
|
||||
out.println("Error: " + e);
|
||||
@ -1063,7 +1041,7 @@ public class CommandProcessor {
|
||||
Oop oop = VM.getVM().getObjectHeap().newOop(handle);
|
||||
node = new OopTreeNodeAdapter(oop, null);
|
||||
|
||||
out.println("instance of " + node.getValue() + " @ " + a +
|
||||
out.println("instance of " + node.getValue() +
|
||||
" (size = " + oop.getObjectSize() + ")");
|
||||
} else if (VM.getVM().getCodeCache().contains(a)) {
|
||||
CodeBlob blob = VM.getVM().getCodeCache().findBlobUnsafe(a);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -94,6 +94,98 @@ public class ClhsdbInspect {
|
||||
expStrMap.put(cmd, List.of(tokensMap.get(key)));
|
||||
test.run(theApp.getPid(), cmds, expStrMap, null);
|
||||
}
|
||||
|
||||
// This part is testing JDK-8261269. When inspecting a java object, we want to make
|
||||
// sure the address is not printed twice and that "Oop for ..." is not printed twice.
|
||||
//
|
||||
// The goal of this test is to dump the Class instance for java.lang.System. It contains
|
||||
// some Oop statics, and that's where the redundant "Oop for..." was noticed. The script
|
||||
// looks something like this:
|
||||
//
|
||||
// hsdb> class java.lang.System
|
||||
// java/lang/System @0x000000080000f388
|
||||
//
|
||||
// hsdb> inspect 0x000000080000f388
|
||||
// Type is InstanceKlass (size of 480)
|
||||
// ...
|
||||
// OopHandle Klass::_java_mirror: OopHandle @ 0x000000080000f400
|
||||
// ...
|
||||
//
|
||||
// hsdb> examine 0x000000080000f400
|
||||
// 0x000000080000f400: 0x00007fd8b812e5e8
|
||||
//
|
||||
// hsdb> examine 0x00007fd8b812e5e8
|
||||
// 0x00007fd8b812e5e8: 0x00000007fef00770
|
||||
//
|
||||
// hsdb> inspect 0x00000007fef00770
|
||||
// instance of Oop for java/lang/Class @ 0x00000007fef00770 @ 0x00000007fef00770 (size = 160)
|
||||
// in: Oop for java/io/BufferedInputStream @ 0x0000000082005b08 Oop for java/io/BufferedInputStream @ 0x0000000082005b08
|
||||
// out: Oop for java/io/PrintStream @ 0x0000000082007b60 Oop for java/io/PrintStream @ 0x0000000082007b60
|
||||
// err: Oop for java/io/PrintStream @ 0x000000008200e0c8 Oop for java/io/PrintStream @ 0x000000008200e0c8
|
||||
|
||||
String cmd;
|
||||
Map<String, List<String>> expStrMap;
|
||||
Map<String, List<String>> unexpStrMap;
|
||||
|
||||
// Start with the "class java.lang.System"
|
||||
cmd = "class java.lang.System";
|
||||
cmds = List.of(cmd);
|
||||
expStrMap = new HashMap<>();
|
||||
expStrMap.put(cmd, List.of("java.lang.System @0x"));
|
||||
String classCmdOutput = test.run(theApp.getPid(), cmds, expStrMap, null);
|
||||
|
||||
// "inspect" the address produced by the "class java.lang.System". This is the InstanceKlass.
|
||||
String classAddress = classCmdOutput.substring(classCmdOutput.indexOf("@0x")+1);
|
||||
lines = classAddress.split("\\R");
|
||||
classAddress = lines[0];
|
||||
cmd = "inspect " + classAddress;
|
||||
cmds = List.of(cmd);
|
||||
expStrMap = new HashMap<>();
|
||||
expStrMap.put(cmd, List.of("Type is InstanceKlass", "Klass::_java_mirror: OopHandle @"));
|
||||
String inspectCmdOutput = test.run(theApp.getPid(), cmds, expStrMap, null);
|
||||
|
||||
// Get the Klass::_java_mirror value from the InstanceKlass
|
||||
String mirrorPattern = "Klass::_java_mirror: OopHandle @ ";
|
||||
String mirrorAddress = inspectCmdOutput.substring(
|
||||
inspectCmdOutput.indexOf(mirrorPattern) + mirrorPattern.length());
|
||||
lines = mirrorAddress.split("\\R");
|
||||
mirrorAddress = lines[0];
|
||||
|
||||
// Use "examine" to do an indirection of the _java_mirror.
|
||||
cmd = "examine " + mirrorAddress;
|
||||
cmds = List.of(cmd);
|
||||
expStrMap = new HashMap<>();
|
||||
expStrMap.put(cmd, List.of(mirrorAddress + ": 0x"));
|
||||
String examineCmdOutput = test.run(theApp.getPid(), cmds, expStrMap, null);
|
||||
String examineResult = examineCmdOutput.substring(examineCmdOutput.indexOf(": 0x")+2);
|
||||
lines = examineResult.split("\\R");
|
||||
examineResult = lines[0].trim(); // examine leaves a trailing space
|
||||
|
||||
// Do another indirection using "examine" to get to the address of the Class instance.
|
||||
cmd = "examine " + examineResult;
|
||||
cmds = List.of(cmd);
|
||||
expStrMap = new HashMap<>();
|
||||
expStrMap.put(cmd, List.of(examineResult + ": 0x"));
|
||||
examineCmdOutput = test.run(theApp.getPid(), cmds, expStrMap, null);
|
||||
examineResult = examineCmdOutput.substring(examineCmdOutput.indexOf(": 0x")+2);
|
||||
lines = examineResult.split("\\R");
|
||||
examineResult = lines[0].trim(); // examine leaves a trailing space
|
||||
|
||||
// inspect the Class instance
|
||||
String instanceOfString = "instance of Oop for java/lang/Class @ ";
|
||||
String staticFieldString = "Oop for java/io/BufferedInputStream @";
|
||||
cmd = "inspect " + examineResult;
|
||||
cmds = List.of(cmd);
|
||||
expStrMap = new HashMap<>();
|
||||
expStrMap.put(cmd, List.of(instanceOfString + examineResult,
|
||||
"in: " + staticFieldString));
|
||||
unexpStrMap = new HashMap<>();
|
||||
// Make sure we don't see the address of the class intance twice, and make sure
|
||||
// we don't see "Oop for ..." twice for the "in" static field.
|
||||
unexpStrMap.put(cmd, List.of(
|
||||
instanceOfString + examineResult + " @ " + examineResult,
|
||||
"in: " + staticFieldString + " .* " + staticFieldString));
|
||||
inspectCmdOutput = test.run(theApp.getPid(), cmds, expStrMap, unexpStrMap);
|
||||
} catch (SkippedException e) {
|
||||
throw e;
|
||||
} catch (Exception ex) {
|
||||
|
Loading…
Reference in New Issue
Block a user