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