Skip to content

Commit

Permalink
Add new DumpAllSparseHeapEntriesCommand in DDR
Browse files Browse the repository at this point in the history
 - new DumpAllSparseHeapEntriesCommand provides a way to list all
  off-heap entries in the core file, which contain sparse 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 sparse 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 3, 2025
1 parent 0ab22ee commit c21c507
Show file tree
Hide file tree
Showing 4 changed files with 182 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 = required
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 = required
MM_SparseDataTableEntry._dataPtr = required
MM_SparseDataTableEntry._proxyObjPtr = required
MM_SparseDataTableEntry._size = required
MM_SparseVirtualMemory._sparseDataPool = required
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,81 @@
/*
* 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 in SparseDataTableEntry
* (e.g. readAccessHashTable)
*/

public class ObjectToSparseDataHashTable extends HashTable_V1<MM_SparseDataTableEntryPointer>
{
protected 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 class SparseDataHashFn implements HashFunction<MM_SparseDataTableEntryPointer>
{
SparseDataHashFn()
{
super();
}

public UDATA hash(MM_SparseDataTableEntryPointer entry) throws CorruptDataException {
return UDATA.cast(entry._dataPtr());
}
}

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

public boolean equal(MM_SparseDataTableEntryPointer entry1, MM_SparseDataTableEntryPointer entry2) throws CorruptDataException {
return (entry1._dataPtr().getAddress() == entry2._dataPtr().getAddress());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllRegionsCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllRomClassLinearCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllSegmentsCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllSparseHeapEntriesCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpContendedLoadTable;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpModuleCommand;
import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpModuleDirectedExportsCommand;
Expand Down Expand Up @@ -199,6 +200,7 @@ public void run(IVMData vmData, Object[] userData)
toPassBack.add(new FindModulesCommand());
toPassBack.add(new DumpModuleCommand());
toPassBack.add(new DumpPackageCommand());
toPassBack.add(new DumpAllSparseHeapEntriesCommand());
if (J9ConstantPoolCommand.isSupported()) {
toPassBack.add(new J9ConstantPoolCommand());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
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.J9BuildFlags;
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;


public class DumpAllSparseHeapEntriesCommand extends Command
{
public DumpAllSparseHeapEntriesCommand()
{
addCommand("dumpalloffheapentries", "cmd|help", "dump all off heap entries");
}

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) {
if (!J9BuildFlags.J9VM_ENV_DATA64) {
throw new CorruptDataException("off heap would not be supported in 32 bit platform.");
}
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 sparse heap.\n");
}
}

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

0 comments on commit c21c507

Please sign in to comment.