View Javadoc

1   /*
2    * Copyright 2008 Eric Caspole
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
5    * file except in compliance with the License. You may obtain a copy of the License at
6    * 
7    * http://www.apache.org/licenses/LICENSE-2.0
8    * 
9    * Unless required by applicable law or agreed to in writing, software distributed under
10   * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11   * KIND, either express or implied. See the License for the specific language governing
12   * permissions and limitations under the License.
13   */
14   
15  package net.sf.madmap;
16  
17  import java.io.*;
18  import java.util.*;
19  
20  /**
21   * HprofClassElement is the representation of a java class in the heap of the 
22   * hprof target process. It manages the field names for HprofObjects to reduce
23   * the footprint of the HprofObjects. It has fields to add up certain totals 
24   * during the analysis phase.
25   * 
26   * @author ecaspole
27   *  
28   */
29  public class HprofClassElement extends HprofHeapCollectable {
30    String          _type_name;
31    Object[]        _static_names     = null;
32    Object[]        _static_refs      = null; // this field could be removed!!
33    ArrayList       _nonstatic_names  = null;
34    long[]          _childrenRefs     = null;
35    
36    int             _instancesCount   = 0;
37    int             _finalizableCount = 0;
38  
39    long            _instancesSize    = 0;
40    long            _finalizableSize  = 0;
41    long            _super;
42    long            _loader;
43    long            _instance_size;
44    long            _totalRetainedSize = 0;
45    
46    public HprofClassElement( long addr, String tn, int trc, long sooperclass, long loader, ArrayList n, ArrayList r ) {
47      super( addr /*, trc */ );
48      _type_name  = tn;
49      _super        = sooperclass;
50      _loader       = loader;
51      if (( n != null ) && ( r != null )) { 
52        buildActualChildrenRefs( n, r );
53      }
54    }
55  
56    // Constructor for Objects to add their type...
57    public HprofClassElement( long addr, String tn ) {
58      super( addr );    
59      _instance_size = 0;
60      _type_name = tn;
61    }
62  
63    // Constructor for Objects to add their type...
64    public HprofClassElement( long addr, String tn, long size ) {
65      super( addr );
66      _instance_size = size;
67      _type_name = tn;
68    }
69  
70    public long getTotalRetainedSize() { return _retainedSize; }
71  
72    public void setTotalRetainedSize( long newSize) { 
73      _retainedSize = newSize; 
74    }
75  
76    public short[] setNonstaticFieldNames( ArrayList names ) {
77      long      indexes   = 0;
78      boolean   matched   = false;
79      short[]     result;
80      ArrayList currResult = new ArrayList();
81      
82      assert names != null : "names is null!";
83      assert names.size() != 0 : "names is empty!";
84      
85      if ( _nonstatic_names != null ) {
86      
87        for ( short i = 0; i < names.size(); i++, matched = false ) {
88          String s = (String) names.get( i );
89          for ( int j = 0; j < _nonstatic_names.size(); j++ ) {
90            String t = (String) _nonstatic_names.get( j );
91            
92            if ( s == t ) {
93              assert (s == t) == (s.equals( t )) : "field names are not interned correctly." ;
94              currResult.add(j);
95              matched = true;
96            }
97          }
98          
99          if ( ! matched  ) {
100           // Didn't find a match
101           _nonstatic_names.add( s );
102           currResult.add(_nonstatic_names.size() - 1);
103         }
104       }
105     } else {
106       _nonstatic_names = names;
107       for ( int k = 0; k < names.size(); k++ ) {
108         currResult.add(k);
109       }
110     }
111 
112     result = new short[ currResult.size() ];
113     for( int m = 0; m < currResult.size(); m++ ) {
114       result[m] = (short)(int)((Integer)currResult.get(m));
115     }
116     return result;
117   }
118 
119   
120   // This sucks.
121   public void buildActualChildrenRefs( ArrayList n, ArrayList r ) {
122     if ( _super != 0 ) {
123       _childrenRefs = new long[ r.size() + 1 ];
124       _childrenRefs[ 0 ] = _super;
125       for( int i = 1; i < _childrenRefs.length; i++ ) {
126         _childrenRefs[ i ] = ((Long)r.get( i - 1 )).longValue();
127       }
128     } else { 
129       _childrenRefs = longArrayListtoLongArray( r );
130     }
131   
132     _static_names = n.toArray();
133     _static_refs  = r.toArray();
134   }
135 
136   // For updating an already-seen class, when the class is actually seen in the file
137   public void completeClass( String tn, int trc, long s, long loader, ArrayList n, ArrayList r ) {
138     // We could get both java.util.HashMap$Entry and  Ljava/util/HashMap$Entry;  at
139     // the same time from one hsci file...
140     //assert tn.equals( _type_name ) : "Class hash table is messed up." ;
141     
142     //setStackTrace(trc);
143     _super        = s;
144     _loader       = loader;
145     
146     buildActualChildrenRefs( n, r );
147   }
148 
149 
150   public int      getInstanceCount()        { return _instancesCount; }
151   public void     setInstanceCount(int i)   { _instancesCount = i; }
152   public long     getInstanceSize()         { return _instancesSize; }
153   public void     setInstanceSize(long i)   { _instancesSize = i; }
154 
155   public int      getFinalizableCount()        { return _finalizableCount; }
156   public void     setFinalizableCount(int i)   { _finalizableCount = i; }
157   public long     getFinalizableSize()         { return _finalizableSize; }
158   public void     setFinalizableSize(long i)   { _finalizableSize = i; }
159   
160   public String   className()             { return _type_name; }
161 
162   // Classes do not contribute to live size in heap...
163   public long       size()                { return 0; }
164 
165   // Size of an object of this type
166   public long instanceSize() { 
167     return _instance_size; 
168   }
169 
170   // Size of an object of this type, update if an array was seen first
171   public void updateInstanceSize(long sz) { 
172     _instance_size = sz;
173   }
174 
175   public ArrayList  nonstatic_field_names()    { 
176     assert _nonstatic_names != null : "nonstatic_field_names is null!" ;
177     return _nonstatic_names; 
178   }
179 
180   
181   public long children_size() {
182     if ( _static_refs != null && _childrenRefs != null ) {
183       return _childrenRefs.length;
184     }
185     return 0;
186   }
187 
188   
189   public long[]   children()    { return _childrenRefs; }
190 
191   public String toString() {
192     StringBuffer p = new StringBuffer();
193   
194     p.append( "CLS " + Long.toHexString(_objectaddr) + " (name=" + _type_name + /* ", trace=" + getStackTrace() + */ ")\n" );
195     p.append( "  " + "super" + "\t" + Long.toHexString( _super ) + "\n");
196     p.append( "  " + "loader" + "\t" + Long.toHexString( _loader ) + "\n");
197     if ( _static_names != null ) {
198       for (int i = 0; i < _static_names.length; i++ ) {
199         String n = (String) _static_names[ i ];
200         Long r = (Long) _static_refs[ i ];
201         p.append( "  static " + n + "\t" + Long.toHexString( r )  + "\n");
202       }
203     }
204     if ( _nonstatic_names != null ) {
205       p.append("  # _nonstatic_names.length  : " + _nonstatic_names.size() + "\n");
206       p.append("  # _nonstatic_names = " + _nonstatic_names + "\n");
207     }
208     p.append( "  # _instance_size = " + _instance_size + "\n");
209     p.append( "  # instance count = " + getInstanceCount() + "\n");
210     p.append( "  # instance total sz = " + getInstanceSize() + "\n");
211     return p.toString();
212   }
213 }