Skip to content

Commit aea474c

Browse files
committed
8261269: When using clhsdb to "inspect" a java object, clhsdb prints "Oop for..." twice
Reviewed-by: sspitsyn, kevinw
1 parent a7e2e80 commit aea474c

File tree

2 files changed

+95
-25
lines changed

2 files changed

+95
-25
lines changed

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java

+2-24
Original file line numberDiff line numberDiff line change
@@ -267,34 +267,12 @@ void usage() {
267267
out.println("Usage: " + usage);
268268
}
269269

270-
void printOopValue(Oop oop) {
271-
if (oop != null) {
272-
Klass k = oop.getKlass();
273-
Symbol s = k.getName();
274-
if (s != null) {
275-
out.print("Oop for " + s.asString() + " @ ");
276-
} else {
277-
out.print("Oop @ ");
278-
}
279-
Oop.printOopAddressOn(oop, out);
280-
} else {
281-
out.print("null");
282-
}
283-
}
284-
285270
void printNode(SimpleTreeNode node) {
286271
int count = node.getChildCount();
287272
for (int i = 0; i < count; i++) {
288273
try {
289274
SimpleTreeNode field = node.getChild(i);
290-
if (field instanceof OopTreeNodeAdapter) {
291-
out.print(field);
292-
out.print(" ");
293-
printOopValue(((OopTreeNodeAdapter)field).getOop());
294-
out.println();
295-
} else {
296-
out.println(field);
297-
}
275+
out.println(field);
298276
} catch (Exception e) {
299277
out.println();
300278
out.println("Error: " + e);
@@ -1063,7 +1041,7 @@ public void doit(Tokens t) {
10631041
Oop oop = VM.getVM().getObjectHeap().newOop(handle);
10641042
node = new OopTreeNodeAdapter(oop, null);
10651043

1066-
out.println("instance of " + node.getValue() + " @ " + a +
1044+
out.println("instance of " + node.getValue() +
10671045
" (size = " + oop.getObjectSize() + ")");
10681046
} else if (VM.getVM().getCodeCache().contains(a)) {
10691047
CodeBlob blob = VM.getVM().getCodeCache().findBlobUnsafe(a);

test/hotspot/jtreg/serviceability/sa/ClhsdbInspect.java

+93-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -94,6 +94,98 @@ public static void main(String[] args) throws Exception {
9494
expStrMap.put(cmd, List.of(tokensMap.get(key)));
9595
test.run(theApp.getPid(), cmds, expStrMap, null);
9696
}
97+
98+
// This part is testing JDK-8261269. When inspecting a java object, we want to make
99+
// sure the address is not printed twice and that "Oop for ..." is not printed twice.
100+
//
101+
// The goal of this test is to dump the Class instance for java.lang.System. It contains
102+
// some Oop statics, and that's where the redundant "Oop for..." was noticed. The script
103+
// looks something like this:
104+
//
105+
// hsdb> class java.lang.System
106+
// java/lang/System @0x000000080000f388
107+
//
108+
// hsdb> inspect 0x000000080000f388
109+
// Type is InstanceKlass (size of 480)
110+
// ...
111+
// OopHandle Klass::_java_mirror: OopHandle @ 0x000000080000f400
112+
// ...
113+
//
114+
// hsdb> examine 0x000000080000f400
115+
// 0x000000080000f400: 0x00007fd8b812e5e8
116+
//
117+
// hsdb> examine 0x00007fd8b812e5e8
118+
// 0x00007fd8b812e5e8: 0x00000007fef00770
119+
//
120+
// hsdb> inspect 0x00000007fef00770
121+
// instance of Oop for java/lang/Class @ 0x00000007fef00770 @ 0x00000007fef00770 (size = 160)
122+
// in: Oop for java/io/BufferedInputStream @ 0x0000000082005b08 Oop for java/io/BufferedInputStream @ 0x0000000082005b08
123+
// out: Oop for java/io/PrintStream @ 0x0000000082007b60 Oop for java/io/PrintStream @ 0x0000000082007b60
124+
// err: Oop for java/io/PrintStream @ 0x000000008200e0c8 Oop for java/io/PrintStream @ 0x000000008200e0c8
125+
126+
String cmd;
127+
Map<String, List<String>> expStrMap;
128+
Map<String, List<String>> unexpStrMap;
129+
130+
// Start with the "class java.lang.System"
131+
cmd = "class java.lang.System";
132+
cmds = List.of(cmd);
133+
expStrMap = new HashMap<>();
134+
expStrMap.put(cmd, List.of("java.lang.System @0x"));
135+
String classCmdOutput = test.run(theApp.getPid(), cmds, expStrMap, null);
136+
137+
// "inspect" the address produced by the "class java.lang.System". This is the InstanceKlass.
138+
String classAddress = classCmdOutput.substring(classCmdOutput.indexOf("@0x")+1);
139+
lines = classAddress.split("\\R");
140+
classAddress = lines[0];
141+
cmd = "inspect " + classAddress;
142+
cmds = List.of(cmd);
143+
expStrMap = new HashMap<>();
144+
expStrMap.put(cmd, List.of("Type is InstanceKlass", "Klass::_java_mirror: OopHandle @"));
145+
String inspectCmdOutput = test.run(theApp.getPid(), cmds, expStrMap, null);
146+
147+
// Get the Klass::_java_mirror value from the InstanceKlass
148+
String mirrorPattern = "Klass::_java_mirror: OopHandle @ ";
149+
String mirrorAddress = inspectCmdOutput.substring(
150+
inspectCmdOutput.indexOf(mirrorPattern) + mirrorPattern.length());
151+
lines = mirrorAddress.split("\\R");
152+
mirrorAddress = lines[0];
153+
154+
// Use "examine" to do an indirection of the _java_mirror.
155+
cmd = "examine " + mirrorAddress;
156+
cmds = List.of(cmd);
157+
expStrMap = new HashMap<>();
158+
expStrMap.put(cmd, List.of(mirrorAddress + ": 0x"));
159+
String examineCmdOutput = test.run(theApp.getPid(), cmds, expStrMap, null);
160+
String examineResult = examineCmdOutput.substring(examineCmdOutput.indexOf(": 0x")+2);
161+
lines = examineResult.split("\\R");
162+
examineResult = lines[0].trim(); // examine leaves a trailing space
163+
164+
// Do another indirection using "examine" to get to the address of the Class instance.
165+
cmd = "examine " + examineResult;
166+
cmds = List.of(cmd);
167+
expStrMap = new HashMap<>();
168+
expStrMap.put(cmd, List.of(examineResult + ": 0x"));
169+
examineCmdOutput = test.run(theApp.getPid(), cmds, expStrMap, null);
170+
examineResult = examineCmdOutput.substring(examineCmdOutput.indexOf(": 0x")+2);
171+
lines = examineResult.split("\\R");
172+
examineResult = lines[0].trim(); // examine leaves a trailing space
173+
174+
// inspect the Class instance
175+
String instanceOfString = "instance of Oop for java/lang/Class @ ";
176+
String staticFieldString = "Oop for java/io/BufferedInputStream @";
177+
cmd = "inspect " + examineResult;
178+
cmds = List.of(cmd);
179+
expStrMap = new HashMap<>();
180+
expStrMap.put(cmd, List.of(instanceOfString + examineResult,
181+
"in: " + staticFieldString));
182+
unexpStrMap = new HashMap<>();
183+
// Make sure we don't see the address of the class intance twice, and make sure
184+
// we don't see "Oop for ..." twice for the "in" static field.
185+
unexpStrMap.put(cmd, List.of(
186+
instanceOfString + examineResult + " @ " + examineResult,
187+
"in: " + staticFieldString + " .* " + staticFieldString));
188+
inspectCmdOutput = test.run(theApp.getPid(), cmds, expStrMap, unexpStrMap);
97189
} catch (SkippedException e) {
98190
throw e;
99191
} catch (Exception ex) {

0 commit comments

Comments
 (0)