Skip to content

Commit

Permalink
Add new DumpAllOffHeapEntriesCommand in DDR
Browse files Browse the repository at this point in the history
 - new DumpAllOffHeapEntriesCommand provides a way to list all
  off-heap entries in the core file, which contain off heap data
  (only when off-heap has been enabled in jvm and gcpolicy has been set
  to Balanced GC mode).
 - for the rest of cases(off-heap has been disabled or "old core file",
  which did not contain off-heap option at all), print out error message
  "This command only works with the core file,
  which contains off-heap."
 - off-heap entry information includes
   the address of the Array Object,
   the data address and
   the size of array data

Signed-off-by: lhu <[email protected]>
  • Loading branch information
LinHu2016 committed Feb 13, 2025
1 parent 131e430 commit 9caf04b
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 0 deletions.
6 changes: 6 additions & 0 deletions debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,7 @@ MM_GCExtensionsBase.heap = required
MM_GCExtensionsBase.heapRegionManager = required
MM_GCExtensionsBase.indexableObjectModel = required
MM_GCExtensionsBase.isVirtualLargeObjectHeapEnabled = bool
MM_GCExtensionsBase.largeObjectVirtualMemory = MM_SparseVirtualMemory*
MM_GCExtensionsBase.objectModel = required
MM_GCExtensionsBase.realtimeGC = required
MM_GCExtensionsBase.referenceChainWalkerMarkMap = required
Expand Down Expand Up @@ -754,6 +755,11 @@ MM_RegionPoolSegregated._smallAvailableRegions = required
MM_RegionPoolSegregated._smallFullRegions = required
MM_RegionPoolSegregated._splitAvailableListSplitCount = required
MM_SegregatedGC._markingScheme = required
MM_SparseAddressOrderedFixedSizeDataPool._objectToSparseDataTable = J9HashTable*
MM_SparseDataTableEntry._dataPtr = void*
MM_SparseDataTableEntry._proxyObjPtr = void*
MM_SparseDataTableEntry._size = UDATA
MM_SparseVirtualMemory._sparseDataPool = MM_SparseAddressOrderedFixedSizeDataPool*
MM_StringTable._cache = required
MM_StringTable._table = required
MM_StringTable._tableCount = required
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright IBM Corp. and others 2025
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* 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
*/
package com.ibm.j9ddr.vm29.j9;

import com.ibm.j9ddr.CorruptDataException;
import com.ibm.j9ddr.vm29.pointer.generated.J9HashTablePointer;
import com.ibm.j9ddr.vm29.pointer.generated.MM_SparseDataTableEntryPointer;
import com.ibm.j9ddr.vm29.pointer.VoidPointer;
import com.ibm.j9ddr.vm29.types.UDATA;

/**
* ObjectToSparseDataHashTable is used for accessing hash tables {@link HashTable}
* in SparseDataTableEntry {@link MM_SparseDataTableEntryPointer} (e.g. iterator).
*/
public final class ObjectToSparseDataHashTable extends HashTable_V1<MM_SparseDataTableEntryPointer>
{
private ObjectToSparseDataHashTable(
J9HashTablePointer hashTablePointer,
boolean isInline,
Class<MM_SparseDataTableEntryPointer> structType,
HashEqualFunction<MM_SparseDataTableEntryPointer> equalFn,
HashFunction<MM_SparseDataTableEntryPointer> hashFn) throws CorruptDataException
{
super(hashTablePointer, isInline, structType, equalFn, hashFn);
}

/**
* Opens J9HashTable from J9HashTablePointer。
*
* @param structure the J9HashTablePointer
* @throws CorruptDataException when fails to read from structure
*/
public static HashTable<MM_SparseDataTableEntryPointer> fromJ9HashTable(J9HashTablePointer structure) throws CorruptDataException
{
return new ObjectToSparseDataHashTable(structure, false, MM_SparseDataTableEntryPointer.class, new SparseDataHashEqualFn(), new SparseDataHashFn());
}

private static final class SparseDataHashFn implements HashFunction<MM_SparseDataTableEntryPointer>
{
SparseDataHashFn()
{
super();
}

@Override
public UDATA hash(MM_SparseDataTableEntryPointer entry) throws CorruptDataException
{
try {
return UDATA.cast(entry._dataPtr());
} catch (NoSuchFieldException e) {
throw new CorruptDataException(e.getMessage());
}
}
}

private static final class SparseDataHashEqualFn implements HashEqualFunction<MM_SparseDataTableEntryPointer>
{
SparseDataHashEqualFn()
{
super();
}

@Override
public boolean equal(MM_SparseDataTableEntryPointer entry1, MM_SparseDataTableEntryPointer entry2) throws CorruptDataException
{
try {
return entry1._dataPtr().getAddress() == entry2._dataPtr().getAddress();
} catch (NoSuchFieldException e) {
throw new CorruptDataException(e.getMessage());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.ibm.j9ddr.IVMData;
import com.ibm.j9ddr.tools.ddrinteractive.BaseJVMCommands;
import com.ibm.j9ddr.tools.ddrinteractive.ICommand;
import com.ibm.j9ddr.vm29.pointer.generated.J9BuildFlags;
import com.ibm.j9ddr.vm29.pointer.helper.ValueTypeHelper;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.ACCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.AllClassesCommand;
Expand All @@ -41,6 +42,7 @@
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.CoreInfoCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllClassesInModuleCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllClassloadersCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllOffHeapEntriesCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllRamClassLinearCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllRegionsCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllRomClassLinearCommand;
Expand Down Expand Up @@ -199,6 +201,9 @@ public void run(IVMData vmData, Object[] userData)
toPassBack.add(new FindModulesCommand());
toPassBack.add(new DumpModuleCommand());
toPassBack.add(new DumpPackageCommand());
if (J9BuildFlags.J9VM_ENV_DATA64) {
toPassBack.add(new DumpAllOffHeapEntriesCommand());
}
if (J9ConstantPoolCommand.isSupported()) {
toPassBack.add(new J9ConstantPoolCommand());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright IBM Corp. and others 2025
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* 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
*/
package com.ibm.j9ddr.vm29.tools.ddrinteractive.commands;

import java.io.PrintStream;

import com.ibm.j9ddr.CorruptDataException;
import com.ibm.j9ddr.NoSuchFieldException;
import com.ibm.j9ddr.tools.ddrinteractive.Context;
import com.ibm.j9ddr.tools.ddrinteractive.DDRInteractiveCommandException;
import com.ibm.j9ddr.tools.ddrinteractive.Command;
import com.ibm.j9ddr.vm29.j9.HashTable;
import com.ibm.j9ddr.vm29.j9.ObjectToSparseDataHashTable;
import com.ibm.j9ddr.vm29.j9.SlotIterator;
import com.ibm.j9ddr.vm29.j9.gc.GCBase;
import com.ibm.j9ddr.vm29.pointer.generated.J9HashTablePointer;
import com.ibm.j9ddr.vm29.pointer.generated.MM_GCExtensionsPointer;
import com.ibm.j9ddr.vm29.pointer.generated.MM_SparseAddressOrderedFixedSizeDataPoolPointer;
import com.ibm.j9ddr.vm29.pointer.generated.MM_SparseDataTableEntryPointer;
import com.ibm.j9ddr.vm29.pointer.generated.MM_SparseVirtualMemoryPointer;
import com.ibm.j9ddr.vm29.pointer.VoidPointer;
import com.ibm.j9ddr.vm29.types.UDATA;

/**
* Dump all off-heap entries in the core file.
*
* usage: !dumpalloffheapentries
*/
public class DumpAllOffHeapEntriesCommand extends Command
{
public DumpAllOffHeapEntriesCommand()
{
addCommand("dumpalloffheapentries", "cmd|help", "dump all off-heap entries");
}

@Override
public void run(String command, String[] args, Context context, PrintStream out) throws DDRInteractiveCommandException
{
if (0 != args.length) {
String argument = args[0];

if (argument.equalsIgnoreCase("help")) {
help(out);
return;
}
}

try {
MM_GCExtensionsPointer extensions = GCBase.getExtensions();
MM_SparseVirtualMemoryPointer sparseVirualMemory = extensions.largeObjectVirtualMemory();
if (sparseVirualMemory.notNull()) {
MM_SparseAddressOrderedFixedSizeDataPoolPointer sparseAddressOrderedFixedSizeDataPool = sparseVirualMemory._sparseDataPool();
if (sparseAddressOrderedFixedSizeDataPool.notNull()) {
J9HashTablePointer objectToSparseDataTable = sparseAddressOrderedFixedSizeDataPool._objectToSparseDataTable();
if (objectToSparseDataTable.notNull()) {
try {
HashTable<MM_SparseDataTableEntryPointer> readObjectToSparseDataTable = ObjectToSparseDataHashTable.fromJ9HashTable(objectToSparseDataTable);
SlotIterator<MM_SparseDataTableEntryPointer> readSlotIterator = readObjectToSparseDataTable.iterator();
long count = readObjectToSparseDataTable.getCount();
out.printf("List off-heap entries(%,d entries)%n", count);
if (0 < count) {
out.printf("+------------------+------------------+------------------%n");
out.printf("| array object | data address | size %n");
out.printf("+------------------+------------------+------------------%n");
String outputFormat = " 0x%016x 0x%016x 0x%016x%n";

while (readSlotIterator.hasNext()) {
MM_SparseDataTableEntryPointer readSparseDataTableEntryPtr2 = MM_SparseDataTableEntryPointer.cast(readSlotIterator.nextAddress());
VoidPointer dataPrt = readSparseDataTableEntryPtr2._dataPtr();
VoidPointer proxyObjPtr = readSparseDataTableEntryPtr2._proxyObjPtr();
UDATA size = readSparseDataTableEntryPtr2._size();

out.append(String.format(
outputFormat,
proxyObjPtr.getAddress(),
dataPrt.getAddress(),
size.longValue()));
}
out.printf("+------------------+------------------+------------------%n");
}
} catch (CorruptDataException e) {
throw new DDRInteractiveCommandException(e);
}
}
}
}
} catch (CorruptDataException | NoSuchFieldException e) {
out.printf("This command only works with the core file, which contains off-heap.%n");
}
}

private static void help(PrintStream out) {
out.append("!dumpalloffheapentries -- dump all off-heap entries");
out.append(nl);
}
}

0 comments on commit 9caf04b

Please sign in to comment.