diff options
Diffstat (limited to 'hit/src/com/android/hit/ClassInstance.java')
-rw-r--r-- | hit/src/com/android/hit/ClassInstance.java | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/hit/src/com/android/hit/ClassInstance.java b/hit/src/com/android/hit/ClassInstance.java new file mode 100644 index 0000000..0869769 --- /dev/null +++ b/hit/src/com/android/hit/ClassInstance.java @@ -0,0 +1,208 @@ +/* + * 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.io.IOException; +import java.util.Set; + +public class ClassInstance extends Instance { + private byte[] mFieldValues; + + public ClassInstance(long id, StackTrace stack, long classId) { + mId = id; + mStack = stack; + mClassId = classId; + } + + public final void loadFieldData(DataInputStream in, int numBytes) + throws IOException { + mFieldValues = new byte[numBytes]; + in.readFully(mFieldValues); + } + + @Override + public void resolveReferences(State state) { + ClassObj isa = mHeap.mState.findClass(mClassId); + + resolve(state, isa, isa.mStaticFieldTypes, isa.mStaticFieldValues); + resolve(state, isa, isa.mFieldTypes, mFieldValues); + } + + private void resolve(State state, ClassObj isa, int[] types, + byte[] values) { + ByteArrayInputStream bais = new ByteArrayInputStream(values); + DataInputStream dis = new DataInputStream(bais); + final int N = types.length; + + /* + * Spin through the list of fields, find all object references, + * and list ourselves as a reference holder. + */ + try { + for (int i = 0; i < N; i++) { + int type = types[i]; + int size = Types.getTypeSize(type); + + if (type == Types.OBJECT) { + long id; + + if (size == 4) { + id = dis.readInt(); + } else { + id = dis.readLong(); + } + + Instance instance = state.findReference(id); + + if (instance != null) { + instance.addParent(this); + } + } else { + dis.skipBytes(size); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public final int getSize() { + ClassObj isa = mHeap.mState.findClass(mClassId); + + return isa.getSize(); + } + + @Override + public final void visit(Set<Instance> resultSet, Filter filter) { + if (resultSet.contains(this)) { + return; + } + + if (filter != null) { + if (filter.accept(this)) { + resultSet.add(this); + } + } else { + resultSet.add(this); + } + + State state = mHeap.mState; + ClassObj isa = state.findClass(mClassId); + int[] types = isa.mFieldTypes; + ByteArrayInputStream bais = new ByteArrayInputStream(mFieldValues); + DataInputStream dis = new DataInputStream(bais); + final int N = types.length; + + /* + * Spin through the list of fields, find all object references, + * and list ourselves as a reference holder. + */ + try { + for (int i = 0; i < N; i++) { + int type = types[i]; + int size = Types.getTypeSize(type); + + if (type == Types.OBJECT) { + long id; + + if (size == 4) { + id = dis.readInt(); + } else { + id = dis.readLong(); + } + + Instance instance = state.findReference(id); + + if (instance != null) { + instance.visit(resultSet, filter); + } + } else { + dis.skipBytes(size); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public final String getTypeName() { + ClassObj theClass = mHeap.mState.findClass(mClassId); + + return theClass.mClassName; + } + + public final String toString() { + return String.format("%s@0x%08x", getTypeName(), mId); + } + + @Override + public String describeReferenceTo(long referent) { + ClassObj isa = mHeap.mState.findClass(mClassId); + int[] types = isa.mFieldTypes; + String[] fieldNames = isa.mFieldNames; + ByteArrayInputStream bais = new ByteArrayInputStream(mFieldValues); + DataInputStream dis = new DataInputStream(bais); + final int N = types.length; + StringBuilder result = new StringBuilder("Referenced in field(s):"); + int numReferences = 0; + + /* + * Spin through the list of fields, add info about the field + * references to the output text. + */ + try { + for (int i = 0; i < N; i++) { + int type = types[i]; + int size = Types.getTypeSize(type); + + if (type == Types.OBJECT) { + long id; + + if (size == 4) { + id = dis.readInt(); + } else { + id = dis.readLong(); + } + + if (id == referent) { + numReferences++; + result.append("\n "); + result.append(fieldNames[i]); + } + } else { + dis.skipBytes(size); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + /* + * TODO: perform a similar loop over the static fields of isa + */ + + if (numReferences == 0) { + return super.describeReferenceTo(referent); + } + + return result.toString(); + } +} |