1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 Google Inc.
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.hit;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ByteArrayInputStream;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.DataInputStream;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Set;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class ClassInstance extends Instance {
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[] mFieldValues;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ClassInstance(long id, StackTrace stack, long classId) {
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mId = id;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mStack = stack;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mClassId = classId;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
32de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void loadFieldData(DataInputStream in, int numBytes)
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws IOException {
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        mFieldValues = new byte[numBytes];
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        in.readFully(mFieldValues);
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void resolveReferences(State state) {
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObj isa = mHeap.mState.findClass(mClassId);
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resolve(state, isa, isa.mStaticFieldTypes, isa.mStaticFieldValues);
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resolve(state, isa, isa.mFieldTypes, mFieldValues);
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro    private void resolve(State state, ClassObj isa, int[] types,
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            byte[] values) {
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ByteArrayInputStream bais = new ByteArrayInputStream(values);
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DataInputStream dis = new DataInputStream(bais);
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        final int N = types.length;
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Spin through the list of fields, find all object references,
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and list ourselves as a reference holder.
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < N; i++) {
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int type = types[i];
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int size = Types.getTypeSize(type);
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (type == Types.OBJECT) {
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        long id;
64de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (size == 4) {
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            id = dis.readInt();
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        } else {
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            id = dis.readLong();
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
70de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        Instance instance = state.findReference(id);
72de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (instance != null) {
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            instance.addParent(this);
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        dis.skipBytes(size);
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (Exception e) {
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            e.printStackTrace();
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final int getSize() {
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObj isa = mHeap.mState.findClass(mClassId);
88de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return isa.getSize();
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void visit(Set<Instance> resultSet, Filter filter) {
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resultSet.contains(this)) {
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
97de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (filter != null) {
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (filter.accept(this)) {
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                resultSet.add(this);
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            resultSet.add(this);
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        State state = mHeap.mState;
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObj isa = state.findClass(mClassId);
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int[] types = isa.mFieldTypes;
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ByteArrayInputStream bais = new ByteArrayInputStream(mFieldValues);
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DataInputStream dis = new DataInputStream(bais);
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        final int N = types.length;
112de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Spin through the list of fields, find all object references,
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and list ourselves as a reference holder.
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < N; i++) {
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int type = types[i];
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int size = Types.getTypeSize(type);
121de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (type == Types.OBJECT) {
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    long id;
124de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (size == 4) {
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        id = dis.readInt();
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        id = dis.readLong();
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
130de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    Instance instance = state.findReference(id);
132de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (instance != null) {
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        instance.visit(resultSet, filter);
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dis.skipBytes(size);
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (Exception e) {
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            e.printStackTrace();
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final String getTypeName() {
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObj theClass = mHeap.mState.findClass(mClassId);
148de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return theClass.mClassName;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final String toString() {
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return String.format("%s@0x%08x", getTypeName(), mId);
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String describeReferenceTo(long referent) {
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ClassObj isa = mHeap.mState.findClass(mClassId);
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int[] types = isa.mFieldTypes;
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String[] fieldNames = isa.mFieldNames;
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ByteArrayInputStream bais = new ByteArrayInputStream(mFieldValues);
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DataInputStream dis = new DataInputStream(bais);
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        final int N = types.length;
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuilder result = new StringBuilder("Referenced in field(s):");
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int numReferences = 0;
166de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Spin through the list of fields, add info about the field
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * references to the output text.
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < N; i++) {
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int type = types[i];
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int size = Types.getTypeSize(type);
175de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (type == Types.OBJECT) {
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    long id;
178de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (size == 4) {
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        id = dis.readInt();
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        id = dis.readLong();
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
184de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (id == referent) {
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        numReferences++;
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        result.append("\n    ");
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        result.append(fieldNames[i]);
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else {
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dis.skipBytes(size);
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (Exception e) {
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            e.printStackTrace();
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *  TODO:  perform a similar loop over the static fields of isa
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (numReferences == 0) {
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return super.describeReferenceTo(referent);
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
205de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result.toString();
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
209