Search in sources :

Example 1 with Instance

use of com.squareup.haha.perflib.Instance in project leakcanary by square.

the class HeapAnalyzer method findTrackedReferences.

public List<TrackedReference> findTrackedReferences(File heapDumpFile) {
    if (!heapDumpFile.exists()) {
        throw new IllegalArgumentException("File does not exist: " + heapDumpFile);
    }
    try {
        HprofBuffer buffer = new MemoryMappedFileBuffer(heapDumpFile);
        HprofParser parser = new HprofParser(buffer);
        Snapshot snapshot = parser.parse();
        deduplicateGcRoots(snapshot);
        ClassObj refClass = snapshot.findClass(KeyedWeakReference.class.getName());
        List<TrackedReference> references = new ArrayList<>();
        for (Instance weakRef : refClass.getInstancesList()) {
            List<ClassInstance.FieldValue> values = classInstanceValues(weakRef);
            String key = asString(fieldValue(values, "key"));
            String name = hasField(values, "name") ? asString(fieldValue(values, "name")) : "(No name field)";
            Instance instance = fieldValue(values, "referent");
            if (instance != null) {
                String className = getClassName(instance);
                List<String> fields = describeFields(instance);
                references.add(new TrackedReference(key, name, className, fields));
            }
        }
        return references;
    } catch (Throwable e) {
        throw new RuntimeException(e);
    }
}
Also used : ClassObj(com.squareup.haha.perflib.ClassObj) Instance(com.squareup.haha.perflib.Instance) ArrayInstance(com.squareup.haha.perflib.ArrayInstance) ClassInstance(com.squareup.haha.perflib.ClassInstance) ArrayList(java.util.ArrayList) HprofBuffer(com.squareup.haha.perflib.io.HprofBuffer) HahaHelper.fieldToString(com.squareup.leakcanary.HahaHelper.fieldToString) HahaHelper.asString(com.squareup.leakcanary.HahaHelper.asString) MemoryMappedFileBuffer(com.squareup.haha.perflib.io.MemoryMappedFileBuffer) Snapshot(com.squareup.haha.perflib.Snapshot) HprofParser(com.squareup.haha.perflib.HprofParser)

Example 2 with Instance

use of com.squareup.haha.perflib.Instance in project leakcanary by square.

the class HeapAnalyzer method findLeakingReference.

private Instance findLeakingReference(String key, Snapshot snapshot) {
    ClassObj refClass = snapshot.findClass(KeyedWeakReference.class.getName());
    List<String> keysFound = new ArrayList<>();
    for (Instance instance : refClass.getInstancesList()) {
        List<ClassInstance.FieldValue> values = classInstanceValues(instance);
        String keyCandidate = asString(fieldValue(values, "key"));
        if (keyCandidate.equals(key)) {
            return fieldValue(values, "referent");
        }
        keysFound.add(keyCandidate);
    }
    throw new IllegalStateException("Could not find weak reference with key " + key + " in " + keysFound);
}
Also used : ClassObj(com.squareup.haha.perflib.ClassObj) Instance(com.squareup.haha.perflib.Instance) ArrayInstance(com.squareup.haha.perflib.ArrayInstance) ClassInstance(com.squareup.haha.perflib.ClassInstance) ArrayList(java.util.ArrayList) HahaHelper.fieldToString(com.squareup.leakcanary.HahaHelper.fieldToString) HahaHelper.asString(com.squareup.leakcanary.HahaHelper.asString)

Example 3 with Instance

use of com.squareup.haha.perflib.Instance in project leakcanary by square.

the class HeapAnalyzer method computeIgnoredBitmapRetainedSize.

/**
   * Bitmaps and bitmap byte arrays are sometimes held by native gc roots, so they aren't included
   * in the retained size because their root dominator is a native gc root.
   * To fix this, we check if the leaking instance is a dominator for each bitmap instance and then
   * add the bitmap size.
   *
   * From experience, we've found that bitmap created in code (Bitmap.createBitmap()) are correctly
   * accounted for, however bitmaps set in layouts are not.
   */
private int computeIgnoredBitmapRetainedSize(Snapshot snapshot, Instance leakingInstance) {
    int bitmapRetainedSize = 0;
    ClassObj bitmapClass = snapshot.findClass("android.graphics.Bitmap");
    for (Instance bitmapInstance : bitmapClass.getInstancesList()) {
        if (isIgnoredDominator(leakingInstance, bitmapInstance)) {
            ArrayInstance mBufferInstance = fieldValue(classInstanceValues(bitmapInstance), "mBuffer");
            // Native bitmaps have mBuffer set to null. We sadly can't account for them.
            if (mBufferInstance == null) {
                continue;
            }
            long bufferSize = mBufferInstance.getTotalRetainedSize();
            long bitmapSize = bitmapInstance.getTotalRetainedSize();
            // the buffer is large, it's easy to detect by checking for bitmap size < buffer size.
            if (bitmapSize < bufferSize) {
                bitmapSize += bufferSize;
            }
            bitmapRetainedSize += bitmapSize;
        }
    }
    return bitmapRetainedSize;
}
Also used : ClassObj(com.squareup.haha.perflib.ClassObj) Instance(com.squareup.haha.perflib.Instance) ArrayInstance(com.squareup.haha.perflib.ArrayInstance) ClassInstance(com.squareup.haha.perflib.ClassInstance) ArrayInstance(com.squareup.haha.perflib.ArrayInstance)

Example 4 with Instance

use of com.squareup.haha.perflib.Instance in project leakcanary by square.

the class ShortestPathFinder method visitRootObj.

private void visitRootObj(LeakNode node) {
    RootObj rootObj = (RootObj) node.instance;
    Instance child = rootObj.getReferredInstance();
    if (rootObj.getRootType() == RootType.JAVA_LOCAL) {
        Instance holder = HahaSpy.allocatingThread(rootObj);
        // We switch the parent node with the thread instance that holds
        // the local reference.
        Exclusion exclusion = null;
        if (node.exclusion != null) {
            exclusion = node.exclusion;
        }
        LeakNode parent = new LeakNode(null, holder, null, null, null);
        enqueue(exclusion, parent, child, "<Java Local>", LOCAL);
    } else {
        enqueue(null, node, child, null, null);
    }
}
Also used : Instance(com.squareup.haha.perflib.Instance) ClassInstance(com.squareup.haha.perflib.ClassInstance) ArrayInstance(com.squareup.haha.perflib.ArrayInstance) RootObj(com.squareup.haha.perflib.RootObj)

Example 5 with Instance

use of com.squareup.haha.perflib.Instance in project leakcanary by square.

the class ShortestPathFinder method visitClassInstance.

private void visitClassInstance(LeakNode node) {
    ClassInstance classInstance = (ClassInstance) node.instance;
    Map<String, Exclusion> ignoredFields = new LinkedHashMap<>();
    ClassObj superClassObj = classInstance.getClassObj();
    Exclusion classExclusion = null;
    while (superClassObj != null) {
        Exclusion params = excludedRefs.classNames.get(superClassObj.getClassName());
        if (params != null) {
            // true overrides null or false.
            if (classExclusion == null || !classExclusion.alwaysExclude) {
                classExclusion = params;
            }
        }
        Map<String, Exclusion> classIgnoredFields = excludedRefs.fieldNameByClassName.get(superClassObj.getClassName());
        if (classIgnoredFields != null) {
            ignoredFields.putAll(classIgnoredFields);
        }
        superClassObj = superClassObj.getSuperClassObj();
    }
    if (classExclusion != null && classExclusion.alwaysExclude) {
        return;
    }
    for (ClassInstance.FieldValue fieldValue : classInstance.getValues()) {
        Exclusion fieldExclusion = classExclusion;
        Field field = fieldValue.getField();
        if (field.getType() != Type.OBJECT) {
            continue;
        }
        Instance child = (Instance) fieldValue.getValue();
        String fieldName = field.getName();
        Exclusion params = ignoredFields.get(fieldName);
        // If we found a field exclusion and it's stronger than a class exclusion
        if (params != null && (fieldExclusion == null || (params.alwaysExclude && !fieldExclusion.alwaysExclude))) {
            fieldExclusion = params;
        }
        enqueue(fieldExclusion, node, child, fieldName, INSTANCE_FIELD);
    }
}
Also used : ClassObj(com.squareup.haha.perflib.ClassObj) Field(com.squareup.haha.perflib.Field) Instance(com.squareup.haha.perflib.Instance) ClassInstance(com.squareup.haha.perflib.ClassInstance) ArrayInstance(com.squareup.haha.perflib.ArrayInstance) ClassInstance(com.squareup.haha.perflib.ClassInstance) LinkedHashMap(java.util.LinkedHashMap)

Aggregations

ArrayInstance (com.squareup.haha.perflib.ArrayInstance)13 ClassInstance (com.squareup.haha.perflib.ClassInstance)13 Instance (com.squareup.haha.perflib.Instance)13 ClassObj (com.squareup.haha.perflib.ClassObj)6 RootObj (com.squareup.haha.perflib.RootObj)4 HahaHelper.asString (com.squareup.leakcanary.HahaHelper.asString)4 HahaHelper.fieldToString (com.squareup.leakcanary.HahaHelper.fieldToString)4 Field (com.squareup.haha.perflib.Field)2 HprofParser (com.squareup.haha.perflib.HprofParser)2 Snapshot (com.squareup.haha.perflib.Snapshot)2 HprofBuffer (com.squareup.haha.perflib.io.HprofBuffer)2 MemoryMappedFileBuffer (com.squareup.haha.perflib.io.MemoryMappedFileBuffer)2 ArrayList (java.util.ArrayList)2 LinkedHashMap (java.util.LinkedHashMap)2 Heap (com.squareup.haha.perflib.Heap)1 RootType (com.squareup.haha.perflib.RootType)1 Type (com.squareup.haha.perflib.Type)1 Map (java.util.Map)1