summaryrefslogtreecommitdiff
path: root/hit/src/com/android/hit/ClassInstance.java
diff options
context:
space:
mode:
Diffstat (limited to 'hit/src/com/android/hit/ClassInstance.java')
-rw-r--r--hit/src/com/android/hit/ClassInstance.java208
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();
+ }
+}