懒惰,直接上代码,用法见JAVA DOC.
1 package com.alibaba.stonelab.javalab.jvm.sizeof;
2
3 import java.lang.instrument.Instrumentation;
4 import java.lang.reflect.Array;
5 import java.lang.reflect.Field;
6 import java.lang.reflect.Modifier;
7 import java.util.IdentityHashMap;
8 import java.util.Map;
9 import java.util.Stack;
10
11 /**
12 * <pre>
13 * 1. MANIFEST.MF
14 * Premain-Class: xxx.yyy.zzz.JavaSizeOf
15 *
16 * 2. MAIN.JAVA
17 * System.out.println(JavaSizeOf.sizeof(new ConcurrentHashMap<Object, Object>()));
18 * System.out.println(JavaSizeOf.sizeof(new String("1234567")));
19 * System.out.println(JavaSizeOf.sizeof(new String("1234")));
20 * System.out.println(JavaSizeOf.sizeof(new Object()));
21 * System.out.println(JavaSizeOf.sizeof(new int[] { 1, 2, 3 }));
22 * System.out.println(JavaSizeOf.sizeof(new CopyOnWriteArrayList<Object>()));
23 * System.out.println(JavaSizeOf.sizeof(null));
24 *
25 * 3. USAGE:
26 * java -javaagent:sizeof.jar xxx.yyy.zzz.Main
27 * </pre>
28 *
29 * @author <a href="mailto:li.jinl@alibaba-inc.com">Stone.J</a> 2013-6-8
30 */
31 public class JavaSizeOf {
32
33 private static Instrumentation inst;
34
35 public static void premain(String agentArgs, Instrumentation inst) {
36 JavaSizeOf.inst = inst;
37 }
38
39 /**
40 * get size of java object.
41 *
42 * @param o
43 * @return
44 */
45 public static long sizeof(Object o) {
46 assert inst != null;
47 Map<Object, Object> visited = new IdentityHashMap<Object, Object>();
48 Stack<Object> visiting = new Stack<Object>();
49 visiting.add(o);
50 long size = 0;
51 while (!visiting.isEmpty()) {
52 size += analysis(visiting, visited);
53 }
54 return size;
55 }
56
57 /**
58 * analysis java object size recursively.
59 *
60 * @param visiting
61 * @param visited
62 * @return
63 */
64 protected static long analysis(Stack<Object> visiting, Map<Object, Object> visited) {
65 Object o = visiting.pop();
66 if (skip(o, visited)) {
67 return 0;
68 }
69 visited.put(o, null);
70 // array.
71 if (o.getClass().isArray() && !o.getClass().getComponentType().isPrimitive()) {
72 if (o.getClass().getName().length() != 2) {
73 for (int i = 0; i < Array.getLength(o); i++) {
74 visiting.add(Array.get(o, i));
75 }
76 }
77 }
78 // object.
79 else {
80 Class<?> clazz = o.getClass();
81 while (clazz != null) {
82 Field[] fields = clazz.getDeclaredFields();
83 for (Field field : fields) {
84 if (Modifier.isStatic(field.getModifiers())) {
85 continue;
86 }
87 if (field.getType().isPrimitive()) {
88 continue;
89 }
90 field.setAccessible(true);
91 try {
92 visiting.add(field.get(o));
93 } catch (Exception e) {
94 assert false;
95 }
96 }
97 clazz = clazz.getSuperclass();
98 }
99 }
100 return inst.getObjectSize(o);
101 }
102
103 /**
104 * <pre>
105 * skip statistics.
106 * </pre>
107 *
108 * @param o
109 * @param visited
110 * @return
111 */
112 protected static boolean skip(Object o, Map<Object, Object> visited) {
113 if (o instanceof String) {
114 if (o == ((String) o).intern()) {
115 return true;
116 }
117 }
118 return o == null || visited.containsKey(o);
119 }
120
121 }
122