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.util.Set; 22 23 public class ArrayInstance extends Instance { 24 private int mType; 25 private int mNumEntries; 26 private byte[] mData; 27 28 public ArrayInstance(long id, StackTrace stack, int type, int numEntries, 29 byte[] data) { 30 mId = id; 31 mStack = stack; 32 mType = type; 33 mNumEntries = numEntries; 34 mData = data; 35 } 36 37 public final void resolveReferences(State state) { 38 if (mType != Types.OBJECT) { 39 return; 40 } 41 42 /* 43 * mData holds a stream of object instance ids 44 * Spin through them all and list ourselves as a reference holder. 45 */ 46 int idSize = Types.getTypeSize(mType); 47 final int N = mNumEntries; 48 49 ByteArrayInputStream bais = new ByteArrayInputStream(mData); 50 DataInputStream dis = new DataInputStream(bais); 51 52 for (int i = 0; i < N; i++) { 53 long id; 54 55 try { 56 if (idSize == 4) { 57 id = dis.readInt(); 58 } else { 59 id = dis.readLong(); 60 } 61 62 Instance instance = state.findReference(id); 63 64 if (instance != null) { 65 instance.addParent(this); 66 } 67 } catch (java.io.IOException e) { 68 e.printStackTrace(); 69 } 70 } 71 } 72 73 @Override 74 public final int getSize() { 75 return mData.length; 76 } 77 78 @Override 79 public final void visit(Set<Instance> resultSet, Filter filter) { 80 // If we're in the set then we and our children have been visited 81 if (resultSet.contains(this)) { 82 return; 83 } 84 85 if (null != filter) { 86 if (filter.accept(this)) { 87 resultSet.add(this); 88 } 89 } else { 90 resultSet.add(this); 91 } 92 93 if (mType != Types.OBJECT) { 94 return; 95 } 96 97 /* 98 * mData holds a stream of object instance ids 99 * Spin through them all and visit them 100 */ 101 int idSize = Types.getTypeSize(mType); 102 final int N = mNumEntries; 103 104 ByteArrayInputStream bais = new ByteArrayInputStream(mData); 105 DataInputStream dis = new DataInputStream(bais); 106 State state = mHeap.mState; 107 108 for (int i = 0; i < N; i++) { 109 long id; 110 111 try { 112 if (idSize == 4) { 113 id = dis.readInt(); 114 } else { 115 id = dis.readLong(); 116 } 117 118 Instance instance = state.findReference(id); 119 120 if (instance != null) { 121 instance.visit(resultSet, filter); 122 } 123 } catch (java.io.IOException e) { 124 e.printStackTrace(); 125 } 126 } 127 } 128 129 @Override 130 public final String getTypeName() { 131 return Types.getTypeName(mType) + "[" + mNumEntries + "]"; 132 } 133 134 public final String toString() { 135 return String.format("%s@0x08x", getTypeName(), mId); 136 } 137 138 @Override 139 public String describeReferenceTo(long referent) { 140 // If this isn't an object array then we can't refer to an object 141 if (mType != Types.OBJECT) { 142 return super.describeReferenceTo(referent); 143 } 144 145 int idSize = Types.getTypeSize(mType); 146 final int N = mNumEntries; 147 int numRefs = 0; 148 StringBuilder result = new StringBuilder("Elements ["); 149 ByteArrayInputStream bais = new ByteArrayInputStream(mData); 150 DataInputStream dis = new DataInputStream(bais); 151 152 /* 153 * Spin through all the objects and build up a string describing 154 * all of the array elements that refer to the target object. 155 */ 156 for (int i = 0; i < N; i++) { 157 long id; 158 159 try { 160 if (idSize == 4) { 161 id = dis.readInt(); 162 } else { 163 id = dis.readLong(); 164 } 165 166 if (id == referent) { 167 numRefs++; 168 169 if (numRefs > 1) { 170 result.append(", "); 171 } 172 173 result.append(i); 174 } 175 } catch (java.io.IOException e) { 176 e.printStackTrace(); 177 } 178 } 179 180 if (numRefs == 0) { 181 return super.describeReferenceTo(referent); 182 } 183 184 result.append("]"); 185 186 return result.toString(); 187 } 188 } 189