import com.android.tools.perflib.heap.StackFrame;
import com.android.tools.perflib.heap.StackTrace;
import com.android.tools.perflib.captures.MemoryMappedFileBuffer;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import gnu.trove.TObjectProcedure;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
ClassObj javaLangClass = mSnapshot.findClass("java.lang.Class");
for (Heap heap : mHeaps) {
- long total = 0;
- for (Instance inst : Iterables.concat(heap.getClasses(), heap.getInstances())) {
- Instance dominator = inst.getImmediateDominator();
- if (dominator != null) {
- total += inst.getSize();
-
- if (dominator == Snapshot.SENTINEL_ROOT) {
- mRooted.add(inst);
- }
+ // Use a single element array for the total to act as a reference to a
+ // long.
+ final long[] total = new long[]{0};
+ TObjectProcedure<Instance> processInstance = new TObjectProcedure<Instance>() {
+ @Override
+ public boolean execute(Instance inst) {
+ Instance dominator = inst.getImmediateDominator();
+ if (dominator != null) {
+ total[0] += inst.getSize();
+
+ if (dominator == Snapshot.SENTINEL_ROOT) {
+ mRooted.add(inst);
+ }
- // Properly label the class of a class object.
- if (inst instanceof ClassObj && javaLangClass != null && inst.getClassObj() == null) {
- inst.setClassId(javaLangClass.getId());
- }
+ // Properly label the class of a class object.
+ if (inst instanceof ClassObj && javaLangClass != null && inst.getClassObj() == null) {
+ inst.setClassId(javaLangClass.getId());
+ }
- // Update dominated instances.
- List<Instance> instances = mDominated.get(dominator);
- if (instances == null) {
- instances = new ArrayList<Instance>();
- mDominated.put(dominator, instances);
- }
- instances.add(inst);
-
- // Update sites.
- List<StackFrame> path = Collections.emptyList();
- StackTrace stack = getStack(inst);
- int stackId = getStackTraceSerialNumber(stack);
- if (stack != null) {
- StackFrame[] frames = getStackFrames(stack);
- if (frames != null && frames.length > 0) {
- path = Lists.reverse(Arrays.asList(frames));
+ // Update dominated instances.
+ List<Instance> instances = mDominated.get(dominator);
+ if (instances == null) {
+ instances = new ArrayList<Instance>();
+ mDominated.put(dominator, instances);
}
- }
- mRootSite.add(stackId, 0, path.iterator(), inst);
+ instances.add(inst);
+
+ // Update sites.
+ List<StackFrame> path = Collections.emptyList();
+ StackTrace stack = getStack(inst);
+ int stackId = getStackTraceSerialNumber(stack);
+ if (stack != null) {
+ StackFrame[] frames = getStackFrames(stack);
+ if (frames != null && frames.length > 0) {
+ path = Lists.reverse(Arrays.asList(frames));
+ }
+ }
+ mRootSite.add(stackId, 0, path.iterator(), inst);
- // Update native allocations.
- InstanceUtils.NativeAllocation alloc = InstanceUtils.getNativeAllocation(inst);
- if (alloc != null) {
- mNativeAllocations.add(alloc);
+ // Update native allocations.
+ InstanceUtils.NativeAllocation alloc = InstanceUtils.getNativeAllocation(inst);
+ if (alloc != null) {
+ mNativeAllocations.add(alloc);
+ }
}
+ return true;
}
+ };
+ for (Instance instance : heap.getClasses()) {
+ processInstance.execute(instance);
}
- mHeapSizes.put(heap, total);
+ heap.forEachInstance(processInstance);
+ mHeapSizes.put(heap, total[0]);
}
// Record the roots and their types.
if (inst instanceof ArrayInstance) {
ArrayInstance array = (ArrayInstance)inst;
- if (array.getArrayType() == Type.BYTE && inst.getHardReferences().size() == 1) {
- Instance ref = inst.getHardReferences().get(0);
+ if (array.getArrayType() == Type.BYTE && inst.getHardReverseReferences().size() == 1) {
+ Instance ref = inst.getHardReverseReferences().get(0);
ClassObj clsref = ref.getClassObj();
if (clsref != null && "android.graphics.Bitmap".equals(clsref.getClassName())) {
return ref;
}
Instance referent = null;
- for (Instance ref : inst.getHardReferences()) {
+ for (Instance ref : inst.getHardReverseReferences()) {
if (isInstanceOfClass(ref, "sun.misc.Cleaner")) {
referent = InstanceUtils.getReferent(ref);
if (referent != null) {
private static void printReferences(
Doc doc, Query query, AhatSnapshot snapshot, Instance inst) {
doc.section("Objects with References to this Object");
- if (inst.getHardReferences().isEmpty()) {
+ if (inst.getHardReverseReferences().isEmpty()) {
doc.println(DocString.text("(none)"));
} else {
doc.table(new Column("Object"));
- List<Instance> references = inst.getHardReferences();
+ List<Instance> references = inst.getHardReverseReferences();
SubsetSelector<Instance> selector = new SubsetSelector(query, HARD_REFS_ID, references);
for (Instance ref : selector.selected()) {
doc.row(Value.render(snapshot, ref));
selector.render(doc);
}
- if (inst.getSoftReferences() != null) {
+ if (inst.getSoftReverseReferences() != null) {
doc.section("Objects with Soft References to this Object");
doc.table(new Column("Object"));
- List<Instance> references = inst.getSoftReferences();
+ List<Instance> references = inst.getSoftReverseReferences();
SubsetSelector<Instance> selector = new SubsetSelector(query, SOFT_REFS_ID, references);
for (Instance ref : selector.selected()) {
doc.row(Value.render(snapshot, ref));