Skip to content

Commit 3b14b6f

Browse files
committed
Implement DDR Command: FindInstances
Related: eclipse-openj9#19267 Signed-off-by: Babneet Singh <[email protected]>
1 parent d400c62 commit 3b14b6f

File tree

2 files changed

+161
-0
lines changed

2 files changed

+161
-0
lines changed

debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/GetCommandsTask.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.ExtendedMethodFlagInfoCommand;
6262
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.FindAllModulesCommand;
6363
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.FindAllReadsCommand;
64+
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.FindInstances;
6465
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.FindMethodFromPcCommand;
6566
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.FindModuleByNameCommand;
6667
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.FindModulesCommand;
@@ -207,6 +208,7 @@ public void run(IVMData vmData, Object[] userData)
207208
toPassBack.add(new FlatObjectCommand());
208209
}
209210
toPassBack.add(new VirtualThreadsCommand());
211+
toPassBack.add(new FindInstances());
210212

211213
loadPlugins(toPassBack, loader);
212214

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* Copyright IBM Corp. and others 2024
3+
*
4+
* This program and the accompanying materials are made available under
5+
* the terms of the Eclipse Public License 2.0 which accompanies this
6+
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7+
* or the Apache License, Version 2.0 which accompanies this distribution and
8+
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9+
*
10+
* This Source Code may also be made available under the following
11+
* Secondary Licenses when the conditions for such availability set
12+
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13+
* General Public License, version 2 with the GNU Classpath
14+
* Exception [1] and GNU General Public License, version 2 with the
15+
* OpenJDK Assembly Exception [2].
16+
*
17+
* [1] https://www.gnu.org/software/classpath/license.html
18+
* [2] https://openjdk.org/legal/assembly-exception.html
19+
*
20+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
21+
*/
22+
package com.ibm.j9ddr.vm29.tools.ddrinteractive.commands;
23+
24+
import java.io.PrintStream;
25+
26+
import com.ibm.j9ddr.CorruptDataException;
27+
import com.ibm.j9ddr.tools.ddrinteractive.Command;
28+
import com.ibm.j9ddr.tools.ddrinteractive.CommandUtils;
29+
import com.ibm.j9ddr.tools.ddrinteractive.Context;
30+
import com.ibm.j9ddr.tools.ddrinteractive.DDRInteractiveCommandException;
31+
import com.ibm.j9ddr.tools.ddrinteractive.Table;
32+
import com.ibm.j9ddr.vm29.pointer.generated.J9ClassPointer;
33+
import com.ibm.j9ddr.vm29.pointer.generated.J9ObjectPointer;
34+
import com.ibm.j9ddr.vm29.pointer.helper.J9ClassHelper;
35+
import com.ibm.j9ddr.vm29.pointer.helper.J9ObjectHelper;
36+
37+
import com.ibm.j9ddr.vm29.j9.DataType;
38+
import com.ibm.j9ddr.vm29.j9.walkers.ClassSegmentIterator;
39+
import com.ibm.j9ddr.vm29.pointer.generated.J9ClassPointer;
40+
import com.ibm.j9ddr.vm29.pointer.generated.J9JavaVMPointer;
41+
import com.ibm.j9ddr.vm29.pointer.helper.J9RASHelper;
42+
43+
import com.ibm.j9ddr.vm29.j9.gc.GCHeapRegionDescriptor;
44+
import com.ibm.j9ddr.vm29.j9.gc.GCHeapRegionIterator;
45+
import com.ibm.j9ddr.vm29.j9.gc.GCObjectHeapIterator;
46+
47+
public class FindInstances extends Command
48+
{
49+
private String className;
50+
private J9ClassPointer classPointer;
51+
private Table data;
52+
private long corruptCount;
53+
private long objectsFound;
54+
55+
public FindInstances() {
56+
addCommand("findinstances", "<classname>", "find all instances of the specific class and its subclasses");
57+
}
58+
59+
private static void printUsage (PrintStream out) {
60+
out.println("findinstances <name> - find all instances of the specific class and its subclasses");
61+
}
62+
63+
private boolean parseArgs(PrintStream out, String[] args) throws DDRInteractiveCommandException {
64+
if (args.length != 1) {
65+
out.println("Exactly one argument expected");
66+
return false;
67+
}
68+
String firstArg = args[0];
69+
if (firstArg.equals("help")) {
70+
printUsage(out);
71+
return false;
72+
}
73+
className = firstArg;
74+
return true;
75+
}
76+
77+
@Override
78+
public void run(String command, String[] args, Context context, PrintStream out) throws DDRInteractiveCommandException {
79+
if (args != null) {
80+
if (!parseArgs(out, args)) {
81+
return;
82+
}
83+
}
84+
85+
try {
86+
J9JavaVMPointer vm = J9RASHelper.getVM(DataType.getJ9RASPointer());
87+
ClassSegmentIterator iterator = new ClassSegmentIterator(vm.classMemorySegments());
88+
89+
out.format(
90+
"Searching for class named '%s' in VM=%s%n",
91+
className, Long.toHexString(vm.getAddress()));
92+
93+
/* Reset classPointer for each invocation of the command. */
94+
classPointer = null;
95+
96+
while (iterator.hasNext()) {
97+
J9ClassPointer clsPointer = (J9ClassPointer)iterator.next();
98+
String javaName = J9ClassHelper.getJavaName(clsPointer);
99+
if (className.equals(javaName)) {
100+
String hexString = clsPointer.getHexAddress();
101+
classPointer = clsPointer;
102+
out.format("Found !j9class %s named %s%n", hexString, javaName);
103+
break;
104+
}
105+
}
106+
107+
if (classPointer == null) {
108+
out.format("No class named %s found%n", className);
109+
return;
110+
}
111+
} catch (CorruptDataException e) {
112+
throw new DDRInteractiveCommandException(e);
113+
}
114+
115+
/* Allocate a new instance of Table for each invocation of the command. */
116+
data = new Table("Instances of " + className);
117+
data.row("Address", "Class Name");
118+
119+
/* Reset counts for each invocation of the command. */
120+
corruptCount = 0;
121+
objectsFound = 0;
122+
123+
scanHeap();
124+
125+
out.format("Objects found: %d%n", objectsFound);
126+
out.format("Corruptions encountered: %d%n", corruptCount);
127+
128+
data.render(out);
129+
}
130+
131+
private void scanHeap() {
132+
try {
133+
GCHeapRegionIterator regions = GCHeapRegionIterator.from();
134+
while (regions.hasNext()) {
135+
GCHeapRegionDescriptor region = regions.next();
136+
scanObjects(region);
137+
}
138+
} catch (CorruptDataException e) {
139+
e.printStackTrace();
140+
}
141+
142+
}
143+
144+
private void scanObjects(GCHeapRegionDescriptor region) throws CorruptDataException {
145+
GCObjectHeapIterator heapIterator = GCObjectHeapIterator.fromHeapRegionDescriptor(region, true, true);
146+
while (heapIterator.hasNext()) {
147+
J9ObjectPointer object = heapIterator.next();
148+
try {
149+
J9ClassPointer objClass = J9ObjectHelper.clazz(object);
150+
if (objClass.notNull() && J9ClassHelper.isSameOrSuperClassOf(classPointer, objClass)) {
151+
data.row(object.getHexAddress(), J9ClassHelper.getJavaName(objClass));
152+
objectsFound += 1;
153+
}
154+
} catch (CorruptDataException e) {
155+
corruptCount += 1;
156+
}
157+
}
158+
}
159+
}

0 commit comments

Comments
 (0)