• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.io.ByteArrayInputStream;
20 import java.io.DataInputStream;
21 import java.io.IOException;
22 import java.util.Set;
23 
24 public class ClassInstance extends Instance {
25     private byte[] mFieldValues;
26 
ClassInstance(long id, StackTrace stack, long classId)27     public ClassInstance(long id, StackTrace stack, long classId) {
28         mId = id;
29         mStack = stack;
30         mClassId = classId;
31     }
32 
loadFieldData(DataInputStream in, int numBytes)33     public final void loadFieldData(DataInputStream in, int numBytes)
34             throws IOException {
35         mFieldValues = new byte[numBytes];
36         in.readFully(mFieldValues);
37     }
38 
39     @Override
resolveReferences(State state)40     public void resolveReferences(State state) {
41         ClassObj isa = mHeap.mState.findClass(mClassId);
42 
43         resolve(state, isa, isa.mStaticFieldTypes, isa.mStaticFieldValues);
44         resolve(state, isa, isa.mFieldTypes, mFieldValues);
45     }
46 
resolve(State state, ClassObj isa, int[] types, byte[] values)47     private void resolve(State state, ClassObj isa, int[] types,
48             byte[] values) {
49         ByteArrayInputStream bais = new ByteArrayInputStream(values);
50         DataInputStream dis = new DataInputStream(bais);
51         final int N = types.length;
52 
53         /*
54          * Spin through the list of fields, find all object references,
55          * and list ourselves as a reference holder.
56          */
57         try {
58             for (int i = 0; i < N; i++) {
59                 int type = types[i];
60                 int size = Types.getTypeSize(type);
61 
62                     if (type == Types.OBJECT) {
63                         long id;
64 
65                         if (size == 4) {
66                             id = dis.readInt();
67                         } else {
68                             id = dis.readLong();
69                         }
70 
71                         Instance instance = state.findReference(id);
72 
73                         if (instance != null) {
74                             instance.addParent(this);
75                         }
76                     } else {
77                         dis.skipBytes(size);
78                     }
79             }
80         } catch (Exception e) {
81             e.printStackTrace();
82         }
83     }
84 
85     @Override
getSize()86     public final int getSize() {
87         ClassObj isa = mHeap.mState.findClass(mClassId);
88 
89         return isa.getSize();
90     }
91 
92     @Override
visit(Set<Instance> resultSet, Filter filter)93     public final void visit(Set<Instance> resultSet, Filter filter) {
94         if (resultSet.contains(this)) {
95             return;
96         }
97 
98         if (filter != null) {
99             if (filter.accept(this)) {
100                 resultSet.add(this);
101             }
102         } else {
103             resultSet.add(this);
104         }
105 
106         State state = mHeap.mState;
107         ClassObj isa = state.findClass(mClassId);
108         int[] types = isa.mFieldTypes;
109         ByteArrayInputStream bais = new ByteArrayInputStream(mFieldValues);
110         DataInputStream dis = new DataInputStream(bais);
111         final int N = types.length;
112 
113         /*
114          * Spin through the list of fields, find all object references,
115          * and list ourselves as a reference holder.
116          */
117         try {
118             for (int i = 0; i < N; i++) {
119                 int type = types[i];
120                 int size = Types.getTypeSize(type);
121 
122                 if (type == Types.OBJECT) {
123                     long id;
124 
125                     if (size == 4) {
126                         id = dis.readInt();
127                     } else {
128                         id = dis.readLong();
129                     }
130 
131                     Instance instance = state.findReference(id);
132 
133                     if (instance != null) {
134                         instance.visit(resultSet, filter);
135                     }
136                 } else {
137                     dis.skipBytes(size);
138                 }
139             }
140         } catch (Exception e) {
141             e.printStackTrace();
142         }
143     }
144 
145     @Override
getTypeName()146     public final String getTypeName() {
147         ClassObj theClass = mHeap.mState.findClass(mClassId);
148 
149         return theClass.mClassName;
150     }
151 
toString()152     public final String toString() {
153         return String.format("%s@0x%08x", getTypeName(), mId);
154     }
155 
156     @Override
describeReferenceTo(long referent)157     public String describeReferenceTo(long referent) {
158         ClassObj isa = mHeap.mState.findClass(mClassId);
159         int[] types = isa.mFieldTypes;
160         String[] fieldNames = isa.mFieldNames;
161         ByteArrayInputStream bais = new ByteArrayInputStream(mFieldValues);
162         DataInputStream dis = new DataInputStream(bais);
163         final int N = types.length;
164         StringBuilder result = new StringBuilder("Referenced in field(s):");
165         int numReferences = 0;
166 
167         /*
168          * Spin through the list of fields, add info about the field
169          * references to the output text.
170          */
171         try {
172             for (int i = 0; i < N; i++) {
173                 int type = types[i];
174                 int size = Types.getTypeSize(type);
175 
176                 if (type == Types.OBJECT) {
177                     long id;
178 
179                     if (size == 4) {
180                         id = dis.readInt();
181                     } else {
182                         id = dis.readLong();
183                     }
184 
185                     if (id == referent) {
186                         numReferences++;
187                         result.append("\n    ");
188                         result.append(fieldNames[i]);
189                     }
190                 } else {
191                     dis.skipBytes(size);
192                 }
193             }
194         } catch (Exception e) {
195             e.printStackTrace();
196         }
197 
198         /*
199          *  TODO:  perform a similar loop over the static fields of isa
200          */
201 
202         if (numReferences == 0) {
203             return super.describeReferenceTo(referent);
204         }
205 
206         return result.toString();
207     }
208 }
209