use of com.squareup.haha.perflib.ClassObj 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);
}
}
use of com.squareup.haha.perflib.ClassObj 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);
}
use of com.squareup.haha.perflib.ClassObj 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;
}
use of com.squareup.haha.perflib.ClassObj in project leakcanary by square.
the class HeapAnalyzer method getClassName.
private String getClassName(Instance instance) {
String className;
if (instance instanceof ClassObj) {
ClassObj classObj = (ClassObj) instance;
className = classObj.getClassName();
} else if (instance instanceof ArrayInstance) {
ArrayInstance arrayInstance = (ArrayInstance) instance;
className = arrayInstance.getClassObj().getClassName();
} else {
ClassObj classObj = instance.getClassObj();
className = classObj.getClassName();
}
return className;
}
use of com.squareup.haha.perflib.ClassObj 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);
}
}
Aggregations