KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > iapi > services > cache > ClassSize


1 /*
2
3    Derby - Class org.apache.derby.iapi.services.cache.ClassSize
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.iapi.services.cache;
23
24 import org.apache.derby.iapi.services.sanity.SanityManager;
25
26 import java.lang.Class JavaDoc;
27 import java.lang.reflect.Field JavaDoc;
28 import java.lang.Runtime JavaDoc;
29 import java.lang.InterruptedException JavaDoc;
30 import java.lang.reflect.Modifier JavaDoc;
31
32 public class ClassSize
33 {
34     public static final int refSize;
35     private static final int objectOverhead = 2; // references, not bytes!
36
private static final int booleanSize = 4;
37     private static final int charSize = 4; // Unicode
38
private static final int shortSize = 4;
39     private static final int intSize = 4;
40     private static final int longSize = 8;
41     private static final int floatSize = 4;
42     private static final int doubleSize = 8;
43     private static final int minObjectSize;
44
45     private static boolean dummyCatalog = false; // Used when constructing the catalog to prevent recursion
46

47     static boolean noGuess = false;
48     // noGuess is used in unit testing.
49

50     static boolean unitTest = false;
51     // unitTest is used in unit testing
52

53     private static final int[] wildGuess = {0,16};
54     /* The standard wild guess of the size of an unknown class, the size of 16 references.
55      * Used when the security manager will not let us look at the class fields.
56      */

57
58     /* Do not let the compiler see ClassSizeCatalog. Otherwise it will try to
59      * compile it. This may fail because ClassSizeCatalog.java is not created
60      * until everything else has been compiled. Bury ClassSizeCatalog in a string.
61      */

62     private static java.util.Hashtable JavaDoc catalog;
63     static
64     {
65         try
66         {
67             catalog = (java.util.Hashtable JavaDoc)
68               Class.forName( "org.apache.derby.iapi.services.cache.ClassSizeCatalog").newInstance();
69         }
70         catch( Exception JavaDoc e){};
71
72         // Figure out whether this is a 32 or 64 bit machine.
73
Runtime JavaDoc runtime = Runtime.getRuntime();
74         long memBase = runtime.totalMemory() - runtime.freeMemory();
75         Object JavaDoc[] junk = new Object JavaDoc[10000];
76         long memUsed = runtime.totalMemory() - runtime.freeMemory() - memBase;
77         int sz = (int)((memUsed + junk.length/2)/junk.length);
78         refSize = ( 4 > sz) ? 4 : sz;
79         minObjectSize = 4*refSize;
80     }
81
82     /**
83      * do not try to use the catalog.
84      */

85     public static void setDummyCatalog()
86     {
87         dummyCatalog = true;
88     }
89     /**
90      * Get the estimate of the size of an object reference.
91      *
92      * @return the estimate in bytes.
93      */

94     public static int getRefSize()
95     {
96         return refSize;
97     }
98
99     /**
100      * @return the estimate of the size of a primitive int
101      */

102     public static int getIntSize()
103     {
104         return intSize;
105     }
106
107     /**
108      * The estimate of the size of a class instance depends on whether the JVM uses 32 or 64
109      * bit addresses, that is it depends on the size of an object reference. It is a linear
110      * function of the size of a reference, e.g.
111      * 24 + 5*r
112      * where r is the size of a reference (usually 4 or 8 bytes).
113      *
114      * This method returns the coefficients of the linear function, e.g. {24, 5} in the above
115      * example.
116      *
117      * @param cl A class whose instance size is to be estimated
118      * @return an array of 2 integers. The first integer is the constant part of the function,
119      * the second is the reference size coefficient.
120      */

121     public static int[] getSizeCoefficients( Class JavaDoc cl)
122     {
123         int[] coeff = {0, objectOverhead};
124
125
126         
127         for( ; null != cl; cl = cl.getSuperclass())
128         {
129            Field JavaDoc[] field = cl.getDeclaredFields();
130             if( null != field)
131             {
132                 for( int i = 0; i < field.length; i++)
133                 {
134                     if( ! Modifier.isStatic( field[i].getModifiers()))
135                     {
136                         Class JavaDoc fieldClass = field[i].getType();
137                         if( fieldClass.isArray() || ! fieldClass.isPrimitive())
138                             coeff[1]++;
139                         else // Is simple primitive
140
{
141                             String JavaDoc name = fieldClass.getName();
142
143                             if( name.equals( "int") || name.equals( "I"))
144                                 coeff[0] += intSize;
145                             else if( name.equals( "long") || name.equals( "J"))
146                                 coeff[0] += longSize;
147                             else if( name.equals( "boolean") || name.equals( "Z"))
148                                 coeff[0] += booleanSize;
149                             else if( name.equals( "short") || name.equals( "S"))
150                                 coeff[0] += shortSize;
151                             else if( name.equals( "byte") || name.equals( "B"))
152                                 coeff[0] += 1;
153                             else if( name.equals( "char") || name.equals( "C"))
154                                 coeff[0] += charSize;
155                             else if( name.equals( "float") || name.equals( "F"))
156                                 coeff[0] += floatSize;
157                             else if( name.equals( "double") || name.equals( "D"))
158                                 coeff[0] += doubleSize;
159                             else // What is this??
160
coeff[1]++; // Make a guess: one reference (?)
161
}
162                     }
163                 }
164             }
165         }
166         return coeff;
167     } // end of getSizeCoefficients
168

169     /**
170      * Estimate the static space taken up by a class instance given the coefficients
171      * returned by getSizeCoefficients.
172      *
173      * @param coeff the coefficients
174      *
175      * @return the size estimate, in bytes
176      */

177     public static int estimateBaseFromCoefficients( int[] coeff)
178     {
179         int size = coeff[0] + coeff[1]*refSize;
180         // Round up to a multiple of 8
181
size = (size + 7)/8;
182         size *= 8;
183         return (size < minObjectSize) ? minObjectSize : size;
184     } // end of estimateBaseFromCoefficients
185

186     /**
187      * Estimate the static space taken up by a class instance from cataloged coefficients.
188      *
189      * @param cls the class
190      *
191      * @return the size estimate, in bytes
192      *
193      * @see #estimateBaseFromCoefficients
194      * @see #getSizeCoefficients
195      * see org.apache.derbyBuild.ClassSizeCrawler
196      */

197     public static int estimateBaseFromCatalog( Class JavaDoc cls)
198     {
199         return estimateBaseFromCatalog( cls, false);
200     }
201     
202     private static int estimateBaseFromCatalog( Class JavaDoc cls, boolean addToCatalog)
203     {
204         if( dummyCatalog)
205             return 0;
206         
207         if( SanityManager.DEBUG)
208             SanityManager.ASSERT( catalog != null, "The class size catalog could not be initialized.");
209         
210         int[] coeff = (int[]) catalog.get( cls.getName());
211         if( coeff == null)
212         {
213             try
214             {
215                 coeff = getSizeCoefficients( cls);
216             }
217             catch( Throwable JavaDoc t)
218             {
219                 if( noGuess)
220                     return -2;
221                 coeff = wildGuess;
222             }
223             if( addToCatalog)
224                 catalog.put( cls.getName(), coeff);
225         }
226         return estimateBaseFromCoefficients( coeff);
227     } // end of estimateBaseFromCatalog
228

229
230     /**
231      * Estimate the static space taken up by a class instance. Save the coefficients
232      * in a catalog.
233      *
234      * @param cls the class
235      *
236      * @return the size estimate, in bytes
237      *
238      * @see #estimateBaseFromCoefficients
239      * @see #getSizeCoefficients
240      * see org.apache.derbyBuild.ClassSizeCrawler
241      */

242     public static int estimateAndCatalogBase( Class JavaDoc cls)
243     {
244         return estimateBaseFromCatalog( cls, true);
245     } // end of estimateAndCatalogBase
246

247     /**
248      * Estimate the static space taken up by the fields of a class. This includes the space taken
249      * up by by references (the pointer) but not by the referenced object. So the estimated
250      * size of an array field does not depend on the size of the array. Similarly the size of
251      * an object (reference) field does not depend on the object.
252      *
253      * @return the size estimate in bytes.
254      *
255      * Note that this method will throw a SecurityException if the SecurityManager does not
256      * let this class execute the method Class.getDeclaredFields(). If this is a concern try
257      * to compute the size coefficients at build time.
258      * see org.apache.derbyBuild.ClassSizeCrawler
259      * @see #estimateBaseFromCatalog
260      */

261     public static int estimateBase( Class JavaDoc cl)
262     {
263         return estimateBaseFromCoefficients( getSizeCoefficients( cl));
264     } // End of estimateBase
265

266     /**
267      * @return the estimated overhead of an array. The estimated size of an x[n] array is
268      * estimateArrayOverhead() + n*sizeOf(x).
269      */

270     public static int estimateArrayOverhead()
271     {
272         return minObjectSize;
273     }
274     
275     /**
276      * Estimate the size of a Hashtable entry. In Java 1.2 we can use Map.entry, but this is not
277      * available in earlier versions of Java.
278      *
279      * @return the estimate, in bytes
280      */

281     public static int estimateHashEntrySize()
282     {
283         return objectOverhead + 3*refSize;
284     }
285
286     /**
287      * Estimate the size of a string.
288      *
289      * @return the estimated size, in bytes
290      */

291     public static int estimateMemoryUsage( String JavaDoc str)
292     {
293         if( null == str)
294             return 0;
295         // Since Java uses Unicode assume that each character takes 2 bytes
296
return 2*str.length();
297     }
298 }
299
Popular Tags