package com.squareup.leakcanary; import android.os.Build; import com.squareup.haha.perflib.ArrayInstance; import com.squareup.haha.perflib.ClassInstance; import com.squareup.haha.perflib.ClassObj; import com.squareup.haha.perflib.Field; import com.squareup.haha.perflib.HprofParser; import com.squareup.haha.perflib.Instance; import com.squareup.haha.perflib.RootObj; import com.squareup.haha.perflib.RootType; import com.squareup.haha.perflib.Snapshot; import com.squareup.haha.perflib.Type; import com.squareup.haha.perflib.io.MemoryMappedFileBuffer; import com.squareup.leakcanary.AnalyzerProgressListener; import com.squareup.leakcanary.LeakTraceElement; import com.squareup.leakcanary.Reachability; import com.squareup.leakcanary.ShortestPathFinder; import com.unity3d.ads.metadata.MediationMetaData; import gnu.trove.THashMap; import gnu.trove.TObjectProcedure; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; /* loaded from: classes.dex */ public final class HeapAnalyzer { private static final String ANONYMOUS_CLASS_NAME_PATTERN = "^.+\\$\\d+$"; private final ExcludedRefs excludedRefs; private final AnalyzerProgressListener listener; private final List reachabilityInspectors; @Deprecated public HeapAnalyzer(ExcludedRefs excludedRefs) { this(excludedRefs, AnalyzerProgressListener.NONE, Collections.emptyList()); } private LeakTraceElement buildLeakElement(LeakNode leakNode) { LeakTraceElement.Holder holder; String str; LeakTraceElement.Holder holder2; LeakNode leakNode2 = leakNode.parent; String str2 = null; if (leakNode2 == null) { return null; } Instance instance = leakNode2.instance; if (instance instanceof RootObj) { return null; } List describeFields = describeFields(instance); String className = getClassName(instance); ArrayList arrayList = new ArrayList(); arrayList.add(className); String name = Object.class.getName(); if (instance instanceof ClassInstance) { ClassObj classObj = instance.getClassObj(); while (true) { classObj = classObj.getSuperClassObj(); if (classObj.getClassName().equals(name)) { break; } arrayList.add(classObj.getClassName()); } } if (instance instanceof ClassObj) { holder = LeakTraceElement.Holder.CLASS; } else if (instance instanceof ArrayInstance) { holder = LeakTraceElement.Holder.ARRAY; } else { ClassObj classObj2 = instance.getClassObj(); if (HahaHelper.extendsThread(classObj2)) { LeakTraceElement.Holder holder3 = LeakTraceElement.Holder.THREAD; str = "(named '" + HahaHelper.threadName(instance) + "')"; holder2 = holder3; return new LeakTraceElement(leakNode.leakReference, holder2, arrayList, str, leakNode.exclusion, describeFields); } if (className.matches(ANONYMOUS_CLASS_NAME_PATTERN)) { String className2 = classObj2.getSuperClassObj().getClassName(); if (name.equals(className2)) { holder = LeakTraceElement.Holder.OBJECT; try { Class[] interfaces = Class.forName(classObj2.getClassName()).getInterfaces(); if (interfaces.length > 0) { str2 = "(anonymous implementation of " + interfaces[0].getName() + ")"; } else { str2 = "(anonymous subclass of java.lang.Object)"; } } catch (ClassNotFoundException unused) { } } else { str2 = "(anonymous subclass of " + className2 + ")"; holder = LeakTraceElement.Holder.OBJECT; } } else { holder = LeakTraceElement.Holder.OBJECT; } } holder2 = holder; str = str2; return new LeakTraceElement(leakNode.leakReference, holder2, arrayList, str, leakNode.exclusion, describeFields); } private LeakTrace buildLeakTrace(LeakNode leakNode) { ArrayList arrayList = new ArrayList(); for (LeakNode leakNode2 = new LeakNode(null, null, leakNode, null); leakNode2 != null; leakNode2 = leakNode2.parent) { LeakTraceElement buildLeakElement = buildLeakElement(leakNode2); if (buildLeakElement != null) { arrayList.add(0, buildLeakElement); } } return new LeakTrace(arrayList, computeExpectedReachability(arrayList)); } private List computeExpectedReachability(List list) { Reachability expectedReachability; int i = 1; int size = list.size() - 1; int i2 = 0; int i3 = 0; loop0: while (true) { if (i >= size) { break; } LeakTraceElement leakTraceElement = list.get(i); Iterator it = this.reachabilityInspectors.iterator(); do { if (!it.hasNext()) { break; } expectedReachability = it.next().expectedReachability(leakTraceElement); if (expectedReachability == Reachability.REACHABLE) { i3 = i; } i++; } while (expectedReachability != Reachability.UNREACHABLE); size = i; break loop0; } ArrayList arrayList = new ArrayList(); while (i2 < list.size()) { arrayList.add(i2 <= i3 ? Reachability.REACHABLE : i2 >= size ? Reachability.UNREACHABLE : Reachability.UNKNOWN); i2++; } return arrayList; } private long computeIgnoredBitmapRetainedSize(Snapshot snapshot, Instance instance) { ArrayInstance arrayInstance; long j = 0; for (Instance instance2 : snapshot.findClass("android.graphics.Bitmap").getInstancesList()) { if (isIgnoredDominator(instance, instance2) && (arrayInstance = (ArrayInstance) HahaHelper.fieldValue(HahaHelper.classInstanceValues(instance2), "mBuffer")) != null) { long totalRetainedSize = arrayInstance.getTotalRetainedSize(); long totalRetainedSize2 = instance2.getTotalRetainedSize(); if (totalRetainedSize2 < totalRetainedSize) { totalRetainedSize2 += totalRetainedSize; } j += totalRetainedSize2; } } return j; } private List describeFields(Instance instance) { ArrayList arrayList = new ArrayList(); if (instance instanceof ClassObj) { for (Map.Entry entry : ((ClassObj) instance).getStaticFieldValues().entrySet()) { arrayList.add(new LeakReference(LeakTraceElement.Type.STATIC_FIELD, entry.getKey().getName(), HahaHelper.valueAsString(entry.getValue()))); } } else if (instance instanceof ArrayInstance) { ArrayInstance arrayInstance = (ArrayInstance) instance; if (arrayInstance.getArrayType() == Type.OBJECT) { Object[] values = arrayInstance.getValues(); for (int i = 0; i < values.length; i++) { arrayList.add(new LeakReference(LeakTraceElement.Type.ARRAY_ENTRY, Integer.toString(i), HahaHelper.valueAsString(values[i]))); } } } else { for (Map.Entry entry2 : instance.getClassObj().getStaticFieldValues().entrySet()) { arrayList.add(new LeakReference(LeakTraceElement.Type.STATIC_FIELD, entry2.getKey().getName(), HahaHelper.valueAsString(entry2.getValue()))); } for (ClassInstance.FieldValue fieldValue : ((ClassInstance) instance).getValues()) { arrayList.add(new LeakReference(LeakTraceElement.Type.INSTANCE_FIELD, fieldValue.getField().getName(), HahaHelper.valueAsString(fieldValue.getValue()))); } } return arrayList; } private AnalysisResult findLeakTrace(long j, Snapshot snapshot, Instance instance, boolean z) { long j2; this.listener.onProgressUpdate(AnalyzerProgressListener.Step.FINDING_SHORTEST_PATH); ShortestPathFinder.Result findPath = new ShortestPathFinder(this.excludedRefs).findPath(snapshot, instance); String className = instance.getClassObj().getClassName(); if (findPath.leakingNode == null) { return AnalysisResult.noLeak(className, since(j)); } this.listener.onProgressUpdate(AnalyzerProgressListener.Step.BUILDING_LEAK_TRACE); LeakTrace buildLeakTrace = buildLeakTrace(findPath.leakingNode); if (z) { this.listener.onProgressUpdate(AnalyzerProgressListener.Step.COMPUTING_DOMINATORS); snapshot.computeDominators(); Instance instance2 = findPath.leakingNode.instance; j2 = instance2.getTotalRetainedSize(); if (Build.VERSION.SDK_INT <= 25) { this.listener.onProgressUpdate(AnalyzerProgressListener.Step.COMPUTING_BITMAP_SIZE); j2 += computeIgnoredBitmapRetainedSize(snapshot, instance2); } } else { j2 = -1; } return AnalysisResult.leakDetected(findPath.excludingKnownLeaks, className, buildLeakTrace, j2, since(j)); } private Instance findLeakingReference(String str, Snapshot snapshot) { ClassObj findClass = snapshot.findClass(KeyedWeakReference.class.getName()); if (findClass == null) { throw new IllegalStateException("Could not find the " + KeyedWeakReference.class.getName() + " class in the heap dump."); } ArrayList arrayList = new ArrayList(); Iterator it = findClass.getInstancesList().iterator(); while (it.hasNext()) { List classInstanceValues = HahaHelper.classInstanceValues(it.next()); Object fieldValue = HahaHelper.fieldValue(classInstanceValues, "key"); if (fieldValue == null) { arrayList.add(null); } else { String asString = HahaHelper.asString(fieldValue); if (asString.equals(str)) { return (Instance) HahaHelper.fieldValue(classInstanceValues, "referent"); } arrayList.add(asString); } } throw new IllegalStateException("Could not find weak reference with key " + str + " in " + arrayList); } private String generateRootKey(RootObj rootObj) { return String.format("%s@0x%08x", rootObj.getRootType().getName(), Long.valueOf(rootObj.getId())); } private String getClassName(Instance instance) { return instance instanceof ClassObj ? ((ClassObj) instance).getClassName() : instance instanceof ArrayInstance ? ((ArrayInstance) instance).getClassObj().getClassName() : instance.getClassObj().getClassName(); } private boolean isIgnoredDominator(Instance instance, Instance instance2) { boolean z = false; do { Instance immediateDominator = instance2.getImmediateDominator(); if ((immediateDominator instanceof RootObj) && ((RootObj) immediateDominator).getRootType() == RootType.UNKNOWN) { instance2 = instance2.getNextInstanceToGcRoot(); z = true; } else { instance2 = immediateDominator; } if (instance2 == null) { return false; } } while (instance2 != instance); return z; } private long since(long j) { return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - j); } @Deprecated public AnalysisResult checkForLeak(File file, String str) { return checkForLeak(file, str, true); } void deduplicateGcRoots(Snapshot snapshot) { final THashMap tHashMap = new THashMap(); final Collection gCRoots = snapshot.getGCRoots(); for (RootObj rootObj : gCRoots) { String generateRootKey = generateRootKey(rootObj); if (!tHashMap.containsKey(generateRootKey)) { tHashMap.put(generateRootKey, rootObj); } } gCRoots.clear(); tHashMap.forEach(new TObjectProcedure() { // from class: com.squareup.leakcanary.HeapAnalyzer.1 @Override // gnu.trove.TObjectProcedure public boolean execute(String str) { return gCRoots.add(tHashMap.get(str)); } }); } public List findTrackedReferences(File file) { if (!file.exists()) { throw new IllegalArgumentException("File does not exist: " + file); } try { Snapshot parse = new HprofParser(new MemoryMappedFileBuffer(file)).parse(); deduplicateGcRoots(parse); ClassObj findClass = parse.findClass(KeyedWeakReference.class.getName()); ArrayList arrayList = new ArrayList(); Iterator it = findClass.getInstancesList().iterator(); while (it.hasNext()) { List classInstanceValues = HahaHelper.classInstanceValues(it.next()); String asString = HahaHelper.asString(HahaHelper.fieldValue(classInstanceValues, "key")); String asString2 = HahaHelper.hasField(classInstanceValues, MediationMetaData.KEY_NAME) ? HahaHelper.asString(HahaHelper.fieldValue(classInstanceValues, MediationMetaData.KEY_NAME)) : "(No name field)"; Instance instance = (Instance) HahaHelper.fieldValue(classInstanceValues, "referent"); if (instance != null) { arrayList.add(new TrackedReference(asString, asString2, getClassName(instance), describeFields(instance))); } } return arrayList; } catch (Throwable th) { throw new RuntimeException(th); } } public AnalysisResult checkForLeak(File file, String str, boolean z) { long nanoTime = System.nanoTime(); if (!file.exists()) { return AnalysisResult.failure(new IllegalArgumentException("File does not exist: " + file), since(nanoTime)); } try { this.listener.onProgressUpdate(AnalyzerProgressListener.Step.READING_HEAP_DUMP_FILE); HprofParser hprofParser = new HprofParser(new MemoryMappedFileBuffer(file)); this.listener.onProgressUpdate(AnalyzerProgressListener.Step.PARSING_HEAP_DUMP); Snapshot parse = hprofParser.parse(); this.listener.onProgressUpdate(AnalyzerProgressListener.Step.DEDUPLICATING_GC_ROOTS); deduplicateGcRoots(parse); this.listener.onProgressUpdate(AnalyzerProgressListener.Step.FINDING_LEAKING_REF); Instance findLeakingReference = findLeakingReference(str, parse); return findLeakingReference == null ? AnalysisResult.noLeak(findLeakingReference.getClassObj().getClassName(), since(nanoTime)) : findLeakTrace(nanoTime, parse, findLeakingReference, z); } catch (Throwable th) { return AnalysisResult.failure(th, since(nanoTime)); } } public HeapAnalyzer(ExcludedRefs excludedRefs, AnalyzerProgressListener analyzerProgressListener, List> list) { this.excludedRefs = excludedRefs; this.listener = analyzerProgressListener; this.reachabilityInspectors = new ArrayList(); Iterator> it = list.iterator(); while (it.hasNext()) { try { this.reachabilityInspectors.add(it.next().getDeclaredConstructor(new Class[0]).newInstance(new Object[0])); } catch (Exception e) { throw new RuntimeException(e); } } } }