Skip to content

Commit

Permalink
Bug 576009 Surface suspect thread locals in leak suspects report
Browse files Browse the repository at this point in the history
Add a couple of sections for objects retained by suspects.

Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=576009
Change-Id: I1578e158fcd111fe40167eafbd29536a7d14c2f5
  • Loading branch information
ajohnson1 committed Jul 15, 2023
1 parent c25dda0 commit 8a35d97
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
import org.eclipse.mat.snapshot.query.Icons;
import org.eclipse.mat.snapshot.query.ObjectListResult;
import org.eclipse.mat.snapshot.query.PieFactory;
import org.eclipse.mat.snapshot.query.RetainedSizeDerivedData;
import org.eclipse.mat.snapshot.query.SnapshotQuery;
import org.eclipse.mat.snapshot.registry.TroubleTicketResolverRegistry;
import org.eclipse.mat.util.HTMLUtils;
Expand Down Expand Up @@ -527,6 +528,54 @@ else if (snapshot.isClass(accumulationPointId))
return composite;
}

private void addCommand(QuerySpec spec, String command, int suspects[])
{
if (suspects.length > 0)
{
if (suspects.length <= 30)
{
try
{
StringBuilder sb = new StringBuilder(command);
for (int i : suspects)
{
sb.append(" 0x").append(Long.toHexString(snapshot.mapIdToAddress(i))); //$NON-NLS-1$
}
spec.setCommand(sb.toString());
}
catch (SnapshotException e)
{} // Ignore if problem
}
// Perhaps they are all the instances of a class
try
{
IClass cls = snapshot.getClassOf(suspects[0]);
if (cls.getNumberOfObjects() == suspects.length)
{
//
int a[] = cls.getObjectIds();
int b[] = suspects.clone();
Arrays.sort(a);
Arrays.sort(b);
if (Arrays.equals(a, b))
{
Collection<IClass> cl1 = snapshot.getClassesByName(cls.getName(), false);
if (cl1 != null && cl1.size() == 1)
{
StringBuilder sb = new StringBuilder(command);
sb.append(' ');
sb.append(cls.getName());
spec.setCommand(sb.toString());
}

}
}
}
catch (SnapshotException e)
{}
}
}

private CompositeResult getLeakDescriptionGroupOfObjects(SuspectRecordGroupOfObjects suspect, IProgressListener listener)
throws SnapshotException
{
Expand Down Expand Up @@ -675,6 +724,32 @@ else if (snapshot.isClass(accumulationPointId))
composite.addResult(spec);
}

// add histogram of suspects and show objects they retain
if (true)
{
RefinedResultBuilder rbuilder = SnapshotQuery.lookup("histogram", snapshot) //$NON-NLS-1$
.setArgument("objects", suspectInstances) //$NON-NLS-1$
.refine(listener);
rbuilder.setInlineRetainedSizeCalculation(true);
rbuilder.addDefaultContextDerivedColumn(RetainedSizeDerivedData.PRECISE);
IResult result = rbuilder.build();
QuerySpec qs = new QuerySpec(Messages.LeakHunterQuery_SuspectObjectsByClass, result);
addCommand(qs, "histogram", suspectInstances); //$NON-NLS-1$
qs.set(Params.Html.COLLAPSED, Boolean.TRUE.toString());
composite.addResult(qs);

rbuilder = SnapshotQuery.lookup("show_retained_set", snapshot) //$NON-NLS-1$
.setArgument("objects", suspectInstances) //$NON-NLS-1$
.refine(listener);
rbuilder.setInlineRetainedSizeCalculation(true);
rbuilder.addDefaultContextDerivedColumn(RetainedSizeDerivedData.APPROXIMATE);
result = rbuilder.build();
qs = new QuerySpec(Messages.LeakHunterQuery_AllObjectsByClassRetained, result);
addCommand(qs, "show_retained_set", suspectInstances); //$NON-NLS-1$
qs.set(Params.Html.COLLAPSED, Boolean.TRUE.toString());
composite.addResult(qs);
}

AccumulationPoint accPoint = suspect.getAccumulationPoint();
if (accPoint != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

import org.eclipse.osgi.util.NLS;

/**
* NLS translatable messages for org.eclipse.mat.api
*/
public class Messages extends NLS
{
private static final String BUNDLE_NAME = "org.eclipse.mat.internal.messages"; //$NON-NLS-1$
Expand Down Expand Up @@ -432,6 +435,7 @@ public class Messages extends NLS
public static String LeakHunterQuery_AccumulatedObjects;
public static String LeakHunterQuery_AccumulatedObjectsByClass;
public static String LeakHunterQuery_AllAccumulatedObjectsByClass;
public static String LeakHunterQuery_AllObjectsByClassRetained;
public static String LeakHunterQuery_BiggestInstances;
public static String LeakHunterQuery_BiggestInstancesHeading;
public static String LeakHunterQuery_BiggestInstancesOverview;
Expand Down Expand Up @@ -473,6 +477,7 @@ public class Messages extends NLS
public static String LeakHunterQuery_ShortestPaths;
public static String LeakHunterQuery_SignificantStackFrames;
public static String LeakHunterQuery_StackTraceAvailable;
public static String LeakHunterQuery_SuspectObjectsByClass;
public static String LeakHunterQuery_SystemClassLoader;
public static String LeakHunterQuery_ThreadDetails;
public static String LeakHunterQuery_ThreadLocalVariable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ JettyRequestResolver_URI=URI
LeakHunterQuery_AccumulatedObjects=Accumulated Objects in Dominator Tree
LeakHunterQuery_AccumulatedObjectsByClass=Accumulated Objects by Class in Dominator Tree
LeakHunterQuery_AllAccumulatedObjectsByClass=All Accumulated Objects by Class
LeakHunterQuery_AllObjectsByClassRetained=All Objects by Class Retained by Suspect Objects
LeakHunterQuery_BiggestInstances=Biggest instances:
LeakHunterQuery_BiggestInstancesHeading=Biggest Instances
LeakHunterQuery_BiggestInstancesOverview=Biggest Instances (Overview)
Expand Down Expand Up @@ -431,6 +432,7 @@ LeakHunterQuery_SeeStackstraceVars=See stacktrace with involved local variables
LeakHunterQuery_ShortestPaths=Shortest Paths To the Accumulation Point
LeakHunterQuery_SignificantStackFrames=Significant stack frames and local variables
LeakHunterQuery_StackTraceAvailable=The stacktrace of this Thread is available.
LeakHunterQuery_SuspectObjectsByClass=Suspect Objects by Class
LeakHunterQuery_SystemClassLoader=&lt;system class loader&gt;
LeakHunterQuery_ThreadDetails=Thread Details
LeakHunterQuery_ThreadLocalVariable=Thread <strong><q>{0}</q></strong> has a local variable or reference to <strong><q>{1}</q></strong> which is on the shortest path to <strong><q>{2}</q></strong>.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011, 2022 IBM Corporation.
* Copyright (c) 2011, 2023 IBM Corporation.
* All rights reserved. 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
Expand All @@ -13,6 +13,7 @@
package org.eclipse.mat.tests.snapshot;


import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.core.AllOf.allOf;
Expand All @@ -28,7 +29,6 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.hamcrest.CoreMatchers.nullValue;

import java.io.File;
import java.io.FileOutputStream;
Expand Down Expand Up @@ -1340,7 +1340,7 @@ public void testSuspects2Report() throws SnapshotException, IOException
public void testLeakHunter2ReportJDK6() throws SnapshotException, IOException
{
ISnapshot snapshot2 = TestSnapshots.getSnapshot(TestSnapshots.SUN_JDK6_18_64BIT, false); // Do not dispose this as shared
testLeakHunter2Report(snapshot, snapshot2, 4, 1, 12);
testLeakHunter2Report(snapshot, snapshot2, 4, 1, 14);
}

/**
Expand Down Expand Up @@ -1377,7 +1377,7 @@ public void testLeakHunter2ReportJDK11() throws SnapshotException, IOException
{
ISnapshot snapshot1 = TestSnapshots.getSnapshot(TestSnapshots.ADOPTOPENJDK_HOTSPOT_JDK11_0_4_11_64BIT, false); // Do not dispose this as shared
ISnapshot snapshot2 = TestSnapshots.getSnapshot(TestSnapshots.OPENJDK_JDK11_04_64BIT, false); // Do not dispose this as shared
testLeakHunter2Report(snapshot1, snapshot2, 9, 1, 25);
testLeakHunter2Report(snapshot1, snapshot2, 9, 1, 29);
}

/**
Expand Down Expand Up @@ -1406,7 +1406,7 @@ public void testLeakHunter2ReportJDK11Fresh() throws SnapshotException, IOExcept
SnapshotFactory.dispose(snapshot1);
assertThat(snapshot1.getClassesByName("java.lang.Object", false), nullValue());
ISnapshot snapshot2 = TestSnapshots.getSnapshot(TestSnapshots.OPENJDK_JDK11_04_64BIT, false); // Do not dispose this as shared
IResult r = testLeakHunter2Report(snapshot1, snapshot2, 9, 1, 25);
IResult r = testLeakHunter2Report(snapshot1, snapshot2, 9, 1, 29);
assertNotNull(r);
}

Expand Down

0 comments on commit 8a35d97

Please sign in to comment.