支持递归引用,唯一不支持的就是不等长数组,不过要支持这个也不难,两个原因不改进它: 1.大部分数组都是等长的。 2.这个东西实在没看出有什么实际应用,这个是主要原因。 需要读者对反射和数组有比较深的认识:
package treeroot.util;
import java.lang.reflect.*; import java.util.*;
/** * Compute the size of a Runtime object or Primitive type. * Because the memory allocation is unknown,we just add * all the fields size of a object. * the primitive size is thounght as * boolean:1 * byte:1 * short:2 * char:2 * int:4 * float:4 * long:8 * double:8 * the array size are the sum of all the elements * the null reference is thought to 4 byte. * the Object instance has the size 8. * */ public class Size { final private static int BOOLEAN=1; final private static int BYTE=1; final private static int SHORT=2; final private static int CHAR=2; final private static int INT=4; final private static int FLOAT=4; final private static int LONG=8; final private static int DOUBLE=8; final private static int REFERENCE=4; final private static int OBJECT=8; private static ThreadLocal objs=new ThreadLocal(); private static void init(Object o){ Map map=new IdentityHashMap(); map.put(o,null); objs.set(map); }
public static int sizeof(boolean i){ return BOOLEAN; } public static int sizeof(byte b){ return BYTE; } public static int sizeof(short s){ return SHORT; } public static int sizeof(char c){ return CHAR; } public static int sizeof(int i){ return INT; } public static int sizeof(float f){ return FLOAT; } public static int sizeof(long l){ return LONG; } public static int sizeof(double d){ return DOUBLE; } public static int sizeof(Object o){ init(o); return sizeof0(o); } private static int sizeof0(Object o) { int size=OBJECT; //if the object is null if(o==null) return REFERENCE; Map map=(Map)objs.get(); Class c=o.getClass();
//if it is array if(c.isArray()){ int[] dimension=getDimension(o); int len=dimension.length; Object obj=o; int num=1; for(int j=0;j<len-1;j++) num*=dimension[j]; if(dimension[len-1]==0){ size+=num*REFERENCE; } else{ num*=dimension[len-1]; //处理递归 int[] index; Class type=c; while(type.isArray()) type=type.getComponentType(); //基本类型的数组 if(type.isPrimitive()){ size+=num*sizeofPrimitive(type); } //引用类型数组 else{ for(int k=0;k<num;k++){ index=countToIndex(k,dimension); Object temp=obj; for(int m=0;m<len;m++){ temp=Array.get(temp,index[m]); } //加入数组中的所有对象 if(!map.containsKey(temp)){ size+=sizeof0(temp); map.put(temp,null); } } } } } // all not-static fields Field[] fs=getFields(o.getClass());
for(int i=0;i<fs.length;i++){ Field f=fs[i]; if(!Modifier.isStatic(f.getModifiers())){
Class type=f.getType(); //if it is primitive if(type.isPrimitive()){ size+=sizeofPrimitive(type); } //recurtive else{ Object obj=null; try{ obj=f.get(o); } catch(IllegalAccessException e){ //won't be happen throw new RuntimeException("impossible"); } if(!map.containsKey(obj)){ size+=sizeof0(obj); map.put(obj,null); } } } }
return size; }
private static int[] countToIndex(int count,int[] d){ int[] res=new int[d.length]; int c=count; int i=1; while(c>0){ int t=1; for(int j=i;j<d.length;j++) t*=d[j]; if(t>c) i++; else{ res[i-1]=c/t; c=c%t; } } return res; }
private static int sizeofPrimitive(Class c){ if (c==boolean.class){ return BOOLEAN; } else if(c==byte.class){ return BYTE; } else if(c==char.class){ return CHAR; } else if(c==short.class){ return SHORT; } else if(c==int.class){ return INT; } else if(c==float.class){ return FLOAT; } else if(c==long.class){ return LONG; } else if(c==double.class){ return DOUBLE; } else{ throw new IllegalArgumentException("Thrown by sizeOfPrimitive()"); } } private static int[] getDimension(Object obj){ int dimension=0; Class c=obj.getClass(); while(c.isArray()){ dimension++; c=c.getComponentType(); } int[] res=new int[dimension]; Object o=obj; for(int i=0;i<dimension-1;i++){ res[i]=Array.getLength(o); o=Array.get(o,0); } res[dimension-1]=Array.getLength(o);
return res; } private static Field[] getFields(Class c){ Class superClass=c.getSuperclass(); Field[] s=null; if(superClass!=null){ getFields(superClass); } Field[] fs=c.getDeclaredFields(); //设置为可访问的 Field.setAccessible(fs,true);
//合并 int size=0; if(s!=null) size+=s.length; if(fs!=null) size+=fs.length;
Field[] result=new Field[size]; int index=0; if((s!=null)&&(s.length>0)){ System.arraycopy(s,0,result,0,s.length); index+=s.length; } if((fs!=null)&&(fs.length>0)){ System.arraycopy(fs,0,result,index,fs.length); }
return result; } }

|