use of com.squareup.haha.perflib.Instance in project leakcanary by square.
the class ShortestPathFinder method enqueueGcRoots.
private void enqueueGcRoots(Snapshot snapshot) {
for (RootObj rootObj : snapshot.getGCRoots()) {
switch(rootObj.getRootType()) {
case JAVA_LOCAL:
Instance thread = HahaSpy.allocatingThread(rootObj);
String threadName = threadName(thread);
Exclusion params = excludedRefs.threadNames.get(threadName);
if (params == null || !params.alwaysExclude) {
enqueue(params, null, rootObj, null, null);
}
break;
case INTERNED_STRING:
case DEBUGGER:
case INVALID_TYPE:
// An object that is unreachable from any other root, but not a root itself.
case UNREACHABLE:
case UNKNOWN:
// An object that is in a queue, waiting for a finalizer to run.
case FINALIZING:
break;
case SYSTEM_CLASS:
case VM_INTERNAL:
// A local variable in native code.
case NATIVE_LOCAL:
// A global variable in native code.
case NATIVE_STATIC:
// An object that was referenced from an active thread block.
case THREAD_BLOCK:
// Everything that called the wait() or notify() methods, or that is synchronized.
case BUSY_MONITOR:
case NATIVE_MONITOR:
case REFERENCE_CLEANUP:
// Input or output parameters in native code.
case NATIVE_STACK:
case JAVA_STATIC:
enqueue(null, null, rootObj, null, null);
break;
default:
throw new UnsupportedOperationException("Unknown root type:" + rootObj.getRootType());
}
}
}
use of com.squareup.haha.perflib.Instance in project leakcanary by square.
the class ShortestPathFinder method visitArrayInstance.
private void visitArrayInstance(LeakNode node) {
ArrayInstance arrayInstance = (ArrayInstance) node.instance;
Type arrayType = arrayInstance.getArrayType();
if (arrayType == Type.OBJECT) {
Object[] values = arrayInstance.getValues();
for (int i = 0; i < values.length; i++) {
Instance child = (Instance) values[i];
enqueue(null, node, child, "[" + i + "]", ARRAY_ENTRY);
}
}
}
use of com.squareup.haha.perflib.Instance in project leakcanary by square.
the class HeapAnalyzer method findLeakTrace.
private AnalysisResult findLeakTrace(long analysisStartNanoTime, Snapshot snapshot, Instance leakingRef) {
ShortestPathFinder pathFinder = new ShortestPathFinder(excludedRefs);
ShortestPathFinder.Result result = pathFinder.findPath(snapshot, leakingRef);
// False alarm, no strong reference path to GC Roots.
if (result.leakingNode == null) {
return noLeak(since(analysisStartNanoTime));
}
LeakTrace leakTrace = buildLeakTrace(result.leakingNode);
String className = leakingRef.getClassObj().getClassName();
// Side effect: computes retained size.
snapshot.computeDominators();
Instance leakingInstance = result.leakingNode.instance;
long retainedSize = leakingInstance.getTotalRetainedSize();
retainedSize += computeIgnoredBitmapRetainedSize(snapshot, leakingInstance);
return leakDetected(result.excludingKnownLeaks, className, leakTrace, retainedSize, since(analysisStartNanoTime));
}
use of com.squareup.haha.perflib.Instance in project leakcanary by square.
the class HeapAnalyzer method isIgnoredDominator.
private boolean isIgnoredDominator(Instance dominator, Instance instance) {
boolean foundNativeRoot = false;
while (true) {
Instance immediateDominator = instance.getImmediateDominator();
if (immediateDominator instanceof RootObj && ((RootObj) immediateDominator).getRootType() == RootType.UNKNOWN) {
// Ignore native roots
instance = instance.getNextInstanceToGcRoot();
foundNativeRoot = true;
} else {
instance = immediateDominator;
}
if (instance == null) {
return false;
}
if (instance == dominator) {
return foundNativeRoot;
}
}
}
use of com.squareup.haha.perflib.Instance in project leakcanary by square.
the class HeapAnalyzer method buildLeakElement.
private LeakTraceElement buildLeakElement(LeakNode node) {
if (node.parent == null) {
// Ignore any root node.
return null;
}
Instance holder = node.parent.instance;
if (holder instanceof RootObj) {
return null;
}
LeakTraceElement.Type type = node.referenceType;
String referenceName = node.referenceName;
LeakTraceElement.Holder holderType;
String className;
String extra = null;
List<String> fields = describeFields(holder);
className = getClassName(holder);
if (holder instanceof ClassObj) {
holderType = CLASS;
} else if (holder instanceof ArrayInstance) {
holderType = ARRAY;
} else {
ClassObj classObj = holder.getClassObj();
if (extendsThread(classObj)) {
holderType = THREAD;
String threadName = threadName(holder);
extra = "(named '" + threadName + "')";
} else if (className.matches(ANONYMOUS_CLASS_NAME_PATTERN)) {
String parentClassName = classObj.getSuperClassObj().getClassName();
if (Object.class.getName().equals(parentClassName)) {
holderType = OBJECT;
try {
// This is an anonymous class implementing an interface. The API does not give access
// to the interfaces implemented by the class. We check if it's in the class path and
// use that instead.
Class<?> actualClass = Class.forName(classObj.getClassName());
Class<?>[] interfaces = actualClass.getInterfaces();
if (interfaces.length > 0) {
Class<?> implementedInterface = interfaces[0];
extra = "(anonymous implementation of " + implementedInterface.getName() + ")";
} else {
extra = "(anonymous subclass of java.lang.Object)";
}
} catch (ClassNotFoundException ignored) {
}
} else {
holderType = OBJECT;
// Makes it easier to figure out which anonymous class we're looking at.
extra = "(anonymous subclass of " + parentClassName + ")";
}
} else {
holderType = OBJECT;
}
}
return new LeakTraceElement(referenceName, type, holderType, className, extra, node.exclusion, fields);
}
Aggregations