1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.hadoop.hbase.util;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25
26 import java.lang.reflect.Field;
27 import java.lang.reflect.Modifier;
28
29
30
31
32
33
34
35 public class ClassSize {
36 static final Log LOG = LogFactory.getLog(ClassSize.class);
37
38 private static int nrOfRefsPerObj = 2;
39
40
41 public static final int ARRAY;
42
43
44 public static final int ARRAYLIST;
45
46
47 public static final int BYTE_BUFFER;
48
49
50 public static final int INTEGER;
51
52
53 public static final int MAP_ENTRY;
54
55
56 public static final int OBJECT;
57
58
59 public static final int REFERENCE;
60
61
62 public static final int STRING;
63
64
65 public static final int TREEMAP;
66
67
68 public static final int CONCURRENT_HASHMAP;
69
70
71 public static final int CONCURRENT_HASHMAP_ENTRY;
72
73
74 public static final int CONCURRENT_HASHMAP_SEGMENT;
75
76
77 public static final int CONCURRENT_SKIPLISTMAP;
78
79
80 public static final int CONCURRENT_SKIPLISTMAP_ENTRY;
81
82
83 public static final int REENTRANT_LOCK;
84
85
86 public static final int ATOMIC_LONG;
87
88
89 public static final int ATOMIC_INTEGER;
90
91
92 public static final int ATOMIC_BOOLEAN;
93
94
95 public static final int COPYONWRITE_ARRAYSET;
96
97
98 public static final int COPYONWRITE_ARRAYLIST;
99
100
101
102
103
104 static {
105
106 if (is32BitJVM()) {
107 REFERENCE = 4;
108 } else {
109 REFERENCE = 8;
110 }
111
112 OBJECT = 2 * REFERENCE;
113
114 ARRAY = align(3 * REFERENCE);
115
116 ARRAYLIST = align(OBJECT + align(REFERENCE) + align(ARRAY) +
117 (2 * Bytes.SIZEOF_INT));
118
119
120 BYTE_BUFFER = align(OBJECT + align(REFERENCE) + align(ARRAY) +
121 (5 * Bytes.SIZEOF_INT) +
122 (3 * Bytes.SIZEOF_BOOLEAN) + Bytes.SIZEOF_LONG);
123
124 INTEGER = align(OBJECT + Bytes.SIZEOF_INT);
125
126 MAP_ENTRY = align(OBJECT + 5 * REFERENCE + Bytes.SIZEOF_BOOLEAN);
127
128 TREEMAP = align(OBJECT + (2 * Bytes.SIZEOF_INT) + align(7 * REFERENCE));
129
130 STRING = align(OBJECT + ARRAY + REFERENCE + 3 * Bytes.SIZEOF_INT);
131
132 CONCURRENT_HASHMAP = align((2 * Bytes.SIZEOF_INT) + ARRAY +
133 (6 * REFERENCE) + OBJECT);
134
135 CONCURRENT_HASHMAP_ENTRY = align(REFERENCE + OBJECT + (3 * REFERENCE) +
136 (2 * Bytes.SIZEOF_INT));
137
138 CONCURRENT_HASHMAP_SEGMENT = align(REFERENCE + OBJECT +
139 (3 * Bytes.SIZEOF_INT) + Bytes.SIZEOF_FLOAT + ARRAY);
140
141 CONCURRENT_SKIPLISTMAP = align(Bytes.SIZEOF_INT + OBJECT + (8 * REFERENCE));
142
143 CONCURRENT_SKIPLISTMAP_ENTRY = align(
144 align(OBJECT + (3 * REFERENCE)) +
145 align((OBJECT + (3 * REFERENCE))/2));
146
147 REENTRANT_LOCK = align(OBJECT + (3 * REFERENCE));
148
149 ATOMIC_LONG = align(OBJECT + Bytes.SIZEOF_LONG);
150
151 ATOMIC_INTEGER = align(OBJECT + Bytes.SIZEOF_INT);
152
153 ATOMIC_BOOLEAN = align(OBJECT + Bytes.SIZEOF_BOOLEAN);
154
155 COPYONWRITE_ARRAYSET = align(OBJECT + REFERENCE);
156
157 COPYONWRITE_ARRAYLIST = align(OBJECT + (2 * REFERENCE) + ARRAY);
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175 @SuppressWarnings("unchecked")
176 private static int [] getSizeCoefficients(Class cl, boolean debug) {
177 int primitives = 0;
178 int arrays = 0;
179
180 int references = nrOfRefsPerObj;
181 int index = 0;
182
183 for ( ; null != cl; cl = cl.getSuperclass()) {
184 Field[] field = cl.getDeclaredFields();
185 if (null != field) {
186 for (Field aField : field) {
187 if (Modifier.isStatic(aField.getModifiers())) continue;
188 Class fieldClass = aField.getType();
189 if (fieldClass.isArray()) {
190 arrays++;
191 references++;
192 } else if (!fieldClass.isPrimitive()) {
193 references++;
194 } else {
195 String name = fieldClass.getName();
196
197 if (name.equals("int") || name.equals("I"))
198 primitives += Bytes.SIZEOF_INT;
199 else if (name.equals("long") || name.equals("J"))
200 primitives += Bytes.SIZEOF_LONG;
201 else if (name.equals("boolean") || name.equals("Z"))
202 primitives += Bytes.SIZEOF_BOOLEAN;
203 else if (name.equals("short") || name.equals("S"))
204 primitives += Bytes.SIZEOF_SHORT;
205 else if (name.equals("byte") || name.equals("B"))
206 primitives += Bytes.SIZEOF_BYTE;
207 else if (name.equals("char") || name.equals("C"))
208 primitives += Bytes.SIZEOF_CHAR;
209 else if (name.equals("float") || name.equals("F"))
210 primitives += Bytes.SIZEOF_FLOAT;
211 else if (name.equals("double") || name.equals("D"))
212 primitives += Bytes.SIZEOF_DOUBLE;
213 }
214 if (debug) {
215 if (LOG.isDebugEnabled()) {
216
217 LOG.debug("" + index + " " + aField.getName() + " " + aField.getType());
218 }
219 }
220 index++;
221 }
222 }
223 }
224 return new int [] {primitives, arrays, references};
225 }
226
227
228
229
230
231
232
233
234
235
236 private static long estimateBaseFromCoefficients(int [] coeff, boolean debug) {
237 long prealign_size = coeff[0] + align(coeff[1] * ARRAY) + coeff[2] * REFERENCE;
238
239
240 long size = align(prealign_size);
241 if(debug) {
242 if (LOG.isDebugEnabled()) {
243
244 LOG.debug("Primitives=" + coeff[0] + ", arrays=" + coeff[1] +
245 ", references(includes " + nrOfRefsPerObj +
246 " for object overhead)=" + coeff[2] + ", refSize " + REFERENCE +
247 ", size=" + size + ", prealign_size=" + prealign_size);
248 }
249 }
250 return size;
251 }
252
253
254
255
256
257
258
259
260
261
262
263
264 @SuppressWarnings("unchecked")
265 public static long estimateBase(Class cl, boolean debug) {
266 return estimateBaseFromCoefficients( getSizeCoefficients(cl, debug), debug);
267 }
268
269
270
271
272
273
274 public static int align(int num) {
275 return (int)(align((long)num));
276 }
277
278
279
280
281
282
283 public static long align(long num) {
284
285
286 return ((num + 7) >> 3) << 3;
287 }
288
289
290
291
292
293 public static boolean is32BitJVM() {
294 return System.getProperty("sun.arch.data.model").equals("32");
295 }
296
297 }
298