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