blob: 42e8803573b2889be46a2f2b5c919b92e3c9955c [file] [log] [blame]
/*
* 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();
}
}