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 int index = 0;
189
190 for ( ; null != cl; cl = cl.getSuperclass()) {
191 Field[] field = cl.getDeclaredFields();
192 if (null != field) {
193 for (Field aField : field) {
194 if (Modifier.isStatic(aField.getModifiers())) continue;
195 Class fieldClass = aField.getType();
196 if (fieldClass.isArray()) {
197 arrays++;
198 references++;
199 } else if (!fieldClass.isPrimitive()) {
200 references++;
201 } else {
202 String name = fieldClass.getName();
203
204 if (name.equals("int") || name.equals("I"))
205 primitives += Bytes.SIZEOF_INT;
206 else if (name.equals("long") || name.equals("J"))
207 primitives += Bytes.SIZEOF_LONG;
208 else if (name.equals("boolean") || name.equals("Z"))
209 primitives += Bytes.SIZEOF_BOOLEAN;
210 else if (name.equals("short") || name.equals("S"))
211 primitives += Bytes.SIZEOF_SHORT;
212 else if (name.equals("byte") || name.equals("B"))
213 primitives += Bytes.SIZEOF_BYTE;
214 else if (name.equals("char") || name.equals("C"))
215 primitives += Bytes.SIZEOF_CHAR;
216 else if (name.equals("float") || name.equals("F"))
217 primitives += Bytes.SIZEOF_FLOAT;
218 else if (name.equals("double") || name.equals("D"))
219 primitives += Bytes.SIZEOF_DOUBLE;
220 }
221 if (debug) {
222 if (LOG.isDebugEnabled()) {
223
224 LOG.debug("" + index + " " + aField.getName() + " " + aField.getType());
225 }
226 }
227 index++;
228 }
229 }
230 }
231 return new int [] {primitives, arrays, references};
232 }
233
234
235
236
237
238
239
240
241
242
243 private static long estimateBaseFromCoefficients(int [] coeff, boolean debug) {
244 long prealign_size = coeff[0] + align(coeff[1] * ARRAY) + coeff[2] * REFERENCE;
245
246
247 long size = align(prealign_size);
248 if(debug) {
249 if (LOG.isDebugEnabled()) {
250
251 LOG.debug("Primitives=" + coeff[0] + ", arrays=" + coeff[1] +
252 ", references(includes " + nrOfRefsPerObj +
253 " for object overhead)=" + coeff[2] + ", refSize " + REFERENCE +
254 ", size=" + size + ", prealign_size=" + prealign_size);
255 }
256 }
257 return size;
258 }
259
260
261
262
263
264
265
266
267
268
269
270
271 @SuppressWarnings("unchecked")
272 public static long estimateBase(Class cl, boolean debug) {
273 return estimateBaseFromCoefficients( getSizeCoefficients(cl, debug), debug);
274 }
275
276
277
278
279
280
281 public static int align(int num) {
282 return (int)(align((long)num));
283 }
284
285
286
287
288
289
290 public static long align(long num) {
291
292
293 return ((num + 7) >> 3) << 3;
294 }
295 }
296