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