stone2083

获得Java对象内存占用大小

懒惰,直接上代码,用法见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 

posted on 2013-06-08 17:32 stone2083 阅读(7842) 评论(1)  编辑  收藏 所属分类: java

Feedback

# re: 获得Java对象内存占用大小 2013-06-08 19:16 开发吧

代码很实用,谢谢!  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问