1 /*
2  * Copyright (C) 2016 The Android Open Source Project
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.ahat.heapdump;
18 
19 import java.util.AbstractList;
20 import java.util.Arrays;
21 import java.util.List;
22 
23 /**
24  * A class from a parsed heap dump.
25  * In addition to those methods inherited from {@link AhatInstance}, the class
26  * provides methods for accessing information about the class object, such as
27  * the class loader, superclass, static field values and instance field
28  * descriptors.
29  */
30 public class AhatClassObj extends AhatInstance {
31   private String mClassName;
32   private AhatClassObj mSuperClassObj;
33   private AhatInstance mClassLoader;
34   private FieldValue[] mStaticFieldValues;
35   private Field[] mInstanceFields;
36   private long mStaticFieldsSize;
37   private long mInstanceSize;
38 
AhatClassObj(long id, String className)39   AhatClassObj(long id, String className) {
40     super(id);
41     mClassName = className;
42   }
43 
initialize(AhatClassObj superClass, long instanceSize, Field[] instanceFields, long staticFieldsSize)44   void initialize(AhatClassObj superClass,
45                   long instanceSize,
46                   Field[] instanceFields,
47                   long staticFieldsSize) {
48     mSuperClassObj = superClass;
49     mInstanceSize = instanceSize;
50     mInstanceFields = instanceFields;
51     mStaticFieldsSize = staticFieldsSize;
52   }
53 
initialize(AhatInstance classLoader, FieldValue[] staticFields)54   void initialize(AhatInstance classLoader, FieldValue[] staticFields) {
55     mClassLoader = classLoader;
56     mStaticFieldValues = staticFields;
57   }
58 
59   @Override
getExtraJavaSize()60   long getExtraJavaSize() {
61     return mStaticFieldsSize;
62   }
63 
64   /**
65    * Returns the name of the class this is a class object for.
66    * For example, "java.lang.String".
67    *
68    * @return the name of the class
69    */
getName()70   public String getName() {
71     return mClassName;
72   }
73 
74   /**
75    * Returns the superclass of this class object.
76    *
77    * @return the superclass object
78    */
getSuperClassObj()79   public AhatClassObj getSuperClassObj() {
80     return mSuperClassObj;
81   }
82 
83   /**
84    * Returns the class loader of this class object.
85    *
86    * @return the class loader object
87    */
getClassLoader()88   public AhatInstance getClassLoader() {
89     return mClassLoader;
90   }
91 
92   /**
93    * Returns the size of instances of this object.
94    * The size returned is as reported in the heap dump.
95    *
96    * @return the class instance size
97    */
getInstanceSize()98   public long getInstanceSize() {
99     return mInstanceSize;
100   }
101 
102   /**
103    * Returns the static field values for this class object.
104    *
105    * @return the static field values
106    */
getStaticFieldValues()107   public List<FieldValue> getStaticFieldValues() {
108     return Arrays.asList(mStaticFieldValues);
109   }
110 
111   /**
112    * Returns the fields of instances of this class.
113    * Does not include fields from the super class of this class.
114    *
115    * @return the instance fields
116    */
getInstanceFields()117   public Field[] getInstanceFields() {
118     return mInstanceFields;
119   }
120 
121   @Override
getReferences()122   Iterable<Reference> getReferences() {
123     List<Reference> refs = new AbstractList<Reference>() {
124       @Override
125       public int size() {
126         return mStaticFieldValues.length;
127       }
128 
129       @Override
130       public Reference get(int index) {
131         FieldValue field = mStaticFieldValues[index];
132         Value value = field.value;
133         if (value != null && value.isAhatInstance()) {
134           return new Reference(AhatClassObj.this,
135                                "." + field.name,
136                                value.asAhatInstance(),
137                                Reachability.STRONG);
138         }
139         return null;
140       }
141     };
142     return new SkipNullsIterator(refs);
143   }
144 
isClassObj()145   @Override public boolean isClassObj() {
146     return true;
147   }
148 
asClassObj()149   @Override public AhatClassObj asClassObj() {
150     return this;
151   }
152 
toString()153   @Override public String toString() {
154     return "class " + mClassName;
155   }
156 
newPlaceHolderInstance()157   @Override AhatInstance newPlaceHolderInstance() {
158     return new AhatPlaceHolderClassObj(this);
159   }
160 }
161