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