1 /* 2 * Copyright (C) 2008 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.hit; 18 19 import java.util.ArrayList; 20 import java.util.HashMap; 21 22 public class Heap { 23 String mName; 24 25 // List of individual stack frames 26 HashMap<Long, StackFrame> mFrames = new HashMap<Long, StackFrame>(); 27 28 // List stack traces, which are lists of stack frames 29 HashMap<Integer, StackTrace> mTraces = new HashMap<Integer, StackTrace>(); 30 31 // Root objects such as interned strings, jni locals, etc 32 ArrayList<RootObj> mRoots = new ArrayList<RootObj>(); 33 34 // List of threads 35 HashMap<Integer, ThreadObj> mThreads = new HashMap<Integer, ThreadObj>(); 36 37 // Class definitions 38 HashMap<Long, ClassObj> mClassesById = new HashMap<Long, ClassObj>(); 39 HashMap<String, ClassObj> mClassesByName = new HashMap<String, ClassObj>(); 40 41 // List of instances of above class definitions 42 HashMap<Long, Instance> mInstances = new HashMap<Long, Instance>(); 43 44 // The super-state that this heap is part of 45 State mState; 46 Heap(String name)47 public Heap(String name) { 48 mName = name; 49 } 50 addStackFrame(StackFrame theFrame)51 public final void addStackFrame(StackFrame theFrame) { 52 mFrames.put(theFrame.mId, theFrame); 53 } 54 getStackFrame(long id)55 public final StackFrame getStackFrame(long id) { 56 return mFrames.get(id); 57 } 58 addStackTrace(StackTrace theTrace)59 public final void addStackTrace(StackTrace theTrace) { 60 mTraces.put(theTrace.mSerialNumber, theTrace); 61 } 62 getStackTrace(int traceSerialNumber)63 public final StackTrace getStackTrace(int traceSerialNumber) { 64 return mTraces.get(traceSerialNumber); 65 } 66 getStackTraceAtDepth(int traceSerialNumber, int depth)67 public final StackTrace getStackTraceAtDepth(int traceSerialNumber, 68 int depth) { 69 StackTrace trace = mTraces.get(traceSerialNumber); 70 71 if (trace != null) { 72 trace = trace.fromDepth(depth); 73 } 74 75 return trace; 76 } 77 addRoot(RootObj root)78 public final void addRoot(RootObj root) { 79 root.mIndex = mRoots.size(); 80 mRoots.add(root); 81 } 82 addThread(ThreadObj thread, int serialNumber)83 public final void addThread(ThreadObj thread, int serialNumber) { 84 mThreads.put(serialNumber, thread); 85 } 86 getThread(int serialNumber)87 public final ThreadObj getThread(int serialNumber) { 88 return mThreads.get(serialNumber); 89 } 90 addInstance(long id, Instance instance)91 public final void addInstance(long id, Instance instance) { 92 mInstances.put(id, instance); 93 } 94 getInstance(long id)95 public final Instance getInstance(long id) { 96 return mInstances.get(id); 97 } 98 addClass(long id, ClassObj theClass)99 public final void addClass(long id, ClassObj theClass) { 100 mClassesById.put(id, theClass); 101 mClassesByName.put(theClass.mClassName, theClass); 102 } 103 getClass(long id)104 public final ClassObj getClass(long id) { 105 return mClassesById.get(id); 106 } 107 getClass(String name)108 public final ClassObj getClass(String name) { 109 return mClassesByName.get(name); 110 } 111 dumpInstanceCounts()112 public final void dumpInstanceCounts() { 113 for (ClassObj theClass: mClassesById.values()) { 114 int count = theClass.mInstances.size(); 115 116 if (count > 0) { 117 System.out.println(theClass + ": " + count); 118 } 119 } 120 } 121 dumpSubclasses()122 public final void dumpSubclasses() { 123 for (ClassObj theClass: mClassesById.values()) { 124 int count = theClass.mSubclasses.size(); 125 126 if (count > 0) { 127 System.out.println(theClass); 128 theClass.dumpSubclasses(); 129 } 130 } 131 } 132 dumpSizes()133 public final void dumpSizes() { 134 for (ClassObj theClass: mClassesById.values()) { 135 int size = 0; 136 137 for (Instance instance: theClass.mInstances) { 138 size += instance.getCompositeSize(); 139 } 140 141 if (size > 0) { 142 System.out.println(theClass + ": base " + theClass.getSize() 143 + ", composite " + size); 144 } 145 } 146 } 147 148 /* 149 * Spin through all of the class instances and link them to their 150 * parent class definition objects. Then have each instance resolve 151 * its own internal object references. 152 */ resolveInstanceRefs(State state)153 public final void resolveInstanceRefs(State state) { 154 for (Instance instance : mInstances.values()) { 155 ClassObj theClass = mClassesById.get(instance.mClassId); 156 157 if (theClass == null) { 158 continue; 159 } 160 161 String name = theClass.mClassName; 162 String superclassName = "none"; 163 ClassObj superClass = mClassesById.get(theClass.mSuperclassId); 164 165 if (superClass != null) { 166 superclassName = superClass.mClassName; 167 } 168 169 theClass.addInstance(instance); 170 instance.resolveReferences(state); 171 } 172 } 173 resolveClassStatics(State state)174 public final void resolveClassStatics(State state) { 175 for (ClassObj theClass: mClassesById.values()) { 176 theClass.resolveReferences(state); 177 } 178 } 179 resolveRoots(State state)180 public final void resolveRoots(State state) { 181 for (RootObj root: mRoots) { 182 root.resolveReferences(state); 183 } 184 } 185 } 186