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