diff options
Diffstat (limited to 'hit/src/com/android/hit/ArrayInstance.java')
-rw-r--r-- | hit/src/com/android/hit/ArrayInstance.java | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/hit/src/com/android/hit/ArrayInstance.java b/hit/src/com/android/hit/ArrayInstance.java new file mode 100644 index 0000000..42e8803 --- /dev/null +++ b/hit/src/com/android/hit/ArrayInstance.java @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.hit; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.util.Set; + +public class ArrayInstance extends Instance { + private int mType; + private int mNumEntries; + private byte[] mData; + + public ArrayInstance(long id, StackTrace stack, int type, int numEntries, + byte[] data) { + mId = id; + mStack = stack; + mType = type; + mNumEntries = numEntries; + mData = data; + } + + public final void resolveReferences(State state) { + if (mType != Types.OBJECT) { + return; + } + + /* + * mData holds a stream of object instance ids + * Spin through them all and list ourselves as a reference holder. + */ + int idSize = Types.getTypeSize(mType); + final int N = mNumEntries; + + ByteArrayInputStream bais = new ByteArrayInputStream(mData); + DataInputStream dis = new DataInputStream(bais); + + for (int i = 0; i < N; i++) { + long id; + + try { + if (idSize == 4) { + id = dis.readInt(); + } else { + id = dis.readLong(); + } + + Instance instance = state.findReference(id); + + if (instance != null) { + instance.addParent(this); + } + } catch (java.io.IOException e) { + e.printStackTrace(); + } + } + } + + @Override + public final int getSize() { + return mData.length; + } + + @Override + public final void visit(Set<Instance> resultSet, Filter filter) { + // If we're in the set then we and our children have been visited + if (resultSet.contains(this)) { + return; + } + + if (null != filter) { + if (filter.accept(this)) { + resultSet.add(this); + } + } else { + resultSet.add(this); + } + + if (mType != Types.OBJECT) { + return; + } + + /* + * mData holds a stream of object instance ids + * Spin through them all and visit them + */ + int idSize = Types.getTypeSize(mType); + final int N = mNumEntries; + + ByteArrayInputStream bais = new ByteArrayInputStream(mData); + DataInputStream dis = new DataInputStream(bais); + State state = mHeap.mState; + + for (int i = 0; i < N; i++) { + long id; + + try { + if (idSize == 4) { + id = dis.readInt(); + } else { + id = dis.readLong(); + } + + Instance instance = state.findReference(id); + + if (instance != null) { + instance.visit(resultSet, filter); + } + } catch (java.io.IOException e) { + e.printStackTrace(); + } + } + } + + @Override + public final String getTypeName() { + return Types.getTypeName(mType) + "[" + mNumEntries + "]"; + } + + public final String toString() { + return String.format("%s@0x08x", getTypeName(), mId); + } + + @Override + public String describeReferenceTo(long referent) { + // If this isn't an object array then we can't refer to an object + if (mType != Types.OBJECT) { + return super.describeReferenceTo(referent); + } + + int idSize = Types.getTypeSize(mType); + final int N = mNumEntries; + int numRefs = 0; + StringBuilder result = new StringBuilder("Elements ["); + ByteArrayInputStream bais = new ByteArrayInputStream(mData); + DataInputStream dis = new DataInputStream(bais); + + /* + * Spin through all the objects and build up a string describing + * all of the array elements that refer to the target object. + */ + for (int i = 0; i < N; i++) { + long id; + + try { + if (idSize == 4) { + id = dis.readInt(); + } else { + id = dis.readLong(); + } + + if (id == referent) { + numRefs++; + + if (numRefs > 1) { + result.append(", "); + } + + result.append(i); + } + } catch (java.io.IOException e) { + e.printStackTrace(); + } + } + + if (numRefs == 0) { + return super.describeReferenceTo(referent); + } + + result.append("]"); + + return result.toString(); + } +} |