Home | History | Annotate | Download | only in hit
      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