Skip to content

Commit

Permalink
Bug 581644 Allow stack frames as pseudo-objects for HPROF snapshots
Browse files Browse the repository at this point in the history
Fix export HPROF with remapping and methods as classes.

Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=581644
Change-Id: Ib76af334f42c4fcfe782d3e0b7f47df9e5eae814
  • Loading branch information
ajohnson1 committed Sep 12, 2023
1 parent d55442d commit aab1a3c
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ private RedactType(String s)
public File mapFile;

@Argument(isMandatory = false, advice = Advice.CLASS_NAME_PATTERN, flag = "skip")
public Pattern skipPattern = Pattern.compile("java\\..*|boolean|byte|char|short|int|long|float|double|void|<[a-z ]+>"); //$NON-NLS-1$
public Pattern skipPattern = Pattern.compile("java\\..*|boolean|byte|char|short|int|long|float|double|void|<[a-z ]+>|.*:<[a-zA-Z]+>|.*\\(.*:declaringClass"); //$NON-NLS-1$

@Argument(isMandatory = false, advice = Advice.CLASS_NAME_PATTERN, flag = "avoid")
public Pattern avoidPattern = Pattern.compile(Messages.ExportHprof_AvoidExample);
Expand Down Expand Up @@ -920,7 +920,7 @@ private void loadClassBody(DataOutput os, long startTime, IClass cls) throws IOE
writeID(os, cls.getObjectAddress());
os.writeInt(UNKNOWN_STACK_TRACE_SERIAL); // stack trace serial number
String classname = cls.getName();
classname = remap.renameClassName(classname);
classname = remap.renameClassOrMethodName(classname);
writeString(os, classname);
}

Expand All @@ -941,7 +941,7 @@ private void loadClass(DataOutput os, DataOutputStream3 os2, long startTime, ICl
if (nextStringID != str)
{
String classname = cls.getName();
classname = remap.renameClassName(classname);
classname = remap.renameClassOrMethodName(classname);
writeStringUTF(os, os2, startTime, classname, str);
}

Expand Down Expand Up @@ -2395,6 +2395,8 @@ public String renameMethodName(String className, String method, boolean upper)
}
if (!isRemapped(className))
return method;
if (!isRemapped(className + ":" + method)) //$NON-NLS-1$
return method;
String newcls = renameClassName(className);
String newmn = remap(mn, newcls + methodSep, method, "", true, upper); //$NON-NLS-1$
return newmn.substring(newmn.indexOf(methodSep) + 1);
Expand Down Expand Up @@ -2495,6 +2497,32 @@ else if (i >= 0)
return remap(classname, newpack, cn, last, false, false);
}

/**
* Renames a class, or a method pseudo-class.
* @param classname the class or class+method name
* @return the renamed class name, or the original name if no renaming is to be done for this class
*/
public String renameClassOrMethodName(String classname)
{
if (obfuscated.containsKey(classname))
return obfuscated.get(classname);
if (classname.contains("(")) //$NON-NLS-1$
{
Frame f = Frame.parse("at " + classname); //$NON-NLS-1$
String classname1 = f.clazz;
String method = f.method;
String sig = f.signature;
method = renameMethodName(classname1, method, false);
sig = renameSignature(sig);
String classname2 = renameClassName(classname1) + '.' + method + sig;
obfuscated.put(classname, classname2);
return classname2;
}
else
{
return renameClassName(classname);
}
}

/**
* Map a class name or package name to a new name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -600,8 +600,7 @@ private void readGCWithThreadContext(int gcType, boolean hasLineInfo) throws IOE
{
// With METHODSASCLASSES instead we add references from the stack
// frame to the local
if (!((HprofPreferences.FRAMES_ONLY.equals(METHODSASCLASSES)
|| HprofPreferences.RUNNING_METHODS_AS_CLASSES.equals(METHODSASCLASSES)) && hasLineInfo && lineNumber >= 0))
if (!(READFRAMES && hasLineInfo && lineNumber >= 0))
handler.addGCRoot(id, tid, gcType);
}
else
Expand Down Expand Up @@ -903,8 +902,7 @@ private void dumpThreads() throws IOException

}
}
if (HprofPreferences.FRAMES_ONLY.equals(METHODSASCLASSES)
|| HprofPreferences.RUNNING_METHODS_AS_CLASSES.equals(METHODSASCLASSES))
if (READFRAMES)
{
// Add the stack frames as extra locals
for (int i = 0; i < stack.frameIds.length; ++i)
Expand Down Expand Up @@ -943,8 +941,7 @@ private void dumpThreads() throws IOException
}
}

if (HprofPreferences.FRAMES_ONLY.equals(METHODSASCLASSES)
|| HprofPreferences.RUNNING_METHODS_AS_CLASSES.equals(METHODSASCLASSES))
if (READFRAMES)
{
stackFramesAsObjects();
}
Expand Down Expand Up @@ -1178,6 +1175,14 @@ private void stackFramesAsObjects() throws IOException
{
frameClazz = (ClassImpl)cls;
frameClazz.setClassInstance(clazzMethodType);
for (Field f : cls.getStaticFields())
{
// The file name is not a real heap java.lang.String object, so fix it up here.
if (f.getName().equals(FILE_NAME) && f.getType() == Type.OBJECT)
{
f.setValue(frame.sourceFile);
}
}
}
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.collection.IsArrayWithSize.arrayWithSize;
import static org.hamcrest.collection.IsEmptyCollection.emptyCollectionOf;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.hamcrest.core.IsNull.nullValue;
import static org.hamcrest.number.OrderingComparison.lessThanOrEqualTo;
import static org.hamcrest.collection.IsArrayWithSize.arrayWithSize;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
Expand All @@ -41,7 +41,6 @@
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Serializable;
Expand Down Expand Up @@ -1384,7 +1383,38 @@ public void exportHPROF(boolean compress, boolean chunked, boolean redact, long
CheckedProgressListener checkListener = new CheckedProgressListener(collector);
IResult t = query.execute(checkListener);
assertNotNull(t);
ISnapshot newSnapshot = SnapshotFactory.openSnapshot(newSnapshotFile, Collections.<String,String>emptyMap(), checkListener);

/* Also try sometimes re-parsing new HPROF as frames as pseudo-objects */
final String key = "methodsAsClasses";
final String hprofPlugin = "org.eclipse.mat.hprof";
IEclipsePreferences preferences2 = InstanceScope.INSTANCE.getNode(hprofPlugin);
String prev2 = preferences2.get(key, null);
if (redact)
{
if (hasMethods == Methods.RUNNING_METHODS)
{
preferences2.put(key, "running");
}
else if (hasMethods == Methods.FRAMES_ONLY)
{
preferences2.put(key, "frames");
}
}

ISnapshot newSnapshot;
try
{
newSnapshot = SnapshotFactory.openSnapshot(newSnapshotFile, Collections.<String,String>emptyMap(), checkListener);
}
finally
{
// Restore HPROF
if (prev2 != null)
preferences2.put(key, prev2);
else
preferences2.remove(key);
}

try {
assertEquals("Snapshot prefix filename", new File(tmpdir, fn.getName()).getName(), new File(newSnapshot.getSnapshotInfo().getPrefix()).getName());
SnapshotInfo oldInfo = snapshot.getSnapshotInfo();
Expand Down

0 comments on commit aab1a3c

Please sign in to comment.