开源:对象运行时大小参考实现(sizeof)

原创 2004年12月29日 08:37:00

支持递归引用,唯一不支持的就是不等长数组,不过要支持这个也不难,两个原因不改进它:
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;
 }
}

C++类的实例化对象的大小之sizeof()

C++类的实例化对象的大小之sizeof()
  • houqingdong2012
  • houqingdong2012
  • 2014年10月19日 20:02
  • 2281

C++类的大小——sizeof()

先看这么个问题——已知:class CBase{    int  a;    char *p;};那么运行cout这个应该很简单,两个成员变量所占的大小有嘛——8。可由时候人就是爱犯这个错误:这么简单...
  • lishengwei
  • lishengwei
  • 2008年05月08日 14:54
  • 12370

sizeof计算对象所占内存的大小详解

sizeof 怎样计算整型数组、字符数组、二维数组、类(是否为菱形继承、是否为虚继承等各种情况)的大小,非常详细的解释!!!...
  • skyroben
  • skyroben
  • 2016年11月17日 22:23
  • 1303

漫步IOS--数组、sizeof和函数形参

首先声明,该系列博客记录的重点是C、OBject-C(以后简称OC)相对于Java的不同,还有一些我在编码练习过程中遇到的问题还有解决方法,而并不是一份流水式的完全的学习笔记。还有一些内容是C和OC中...
  • u013465022
  • u013465022
  • 2014年12月23日 09:41
  • 1096

C++类中包含stl容器时,使用sizeof求大小的问题

这里的大小指的是sizeof(a class object)的值,也就是一个类的对象所占的字节大小,原来我一直认为类的大小会随着类成员中容器元素个数的变化而变化,后来想想又想不通,所以写了下面的代码用...
  • shihengzhen101
  • shihengzhen101
  • 2015年11月18日 22:45
  • 1395

sizeof获取数组长度

昨天开始看《算法导论》这本书,第一个算法就是(直接)插入排序,根据书里给出的伪代码写出了C语言代码,也根据自己的理解重新写了一个。虽然实现了算法的基本要求,但有些细节没有处理好,今天就来完善一下。 在...
  • u011852211
  • u011852211
  • 2016年10月06日 21:17
  • 6528

sizeof的作用——解释类中与类之外static变量的情况

今天看程序员面试宝典的时候遇到一个问题,书上有这么一句话:sizeof计算栈中分配的大小。咋一看这句话的时候,很不理解,难道像函数中类似于static、extern const类型的变量的sizeof...
  • yanqi3310510
  • yanqi3310510
  • 2014年06月26日 16:07
  • 690

C语言中 sizeof 运算的值是在编译时还是运行时确定?

在经典的《C语言程序设计》书中说到: C语言提供了一个编译时(compile-time) 一元运算符 sizeof,它可以用来计算任一对象的长度。 表达式 sizeof 对象 以及 siz...
  • keykey__7
  • keykey__7
  • 2016年11月25日 15:18
  • 1654

用sizeof求二维数组的行列大小

#include "stdio.h" #include "conio.h" #define M 2#define N 3main() { int a[M][N]; 
  • lujianfeiccie2009
  • lujianfeiccie2009
  • 2010年11月25日 11:15
  • 13031

sizeof(void*)的大小到底由何决定?(个人理解)

由编译器产生的目标平台的指令集决定的。譬如说x86就是4,x64就是8. sizeof(void*)的含义就是获取一个指针的大小。 指针的本质就是内存地址,因此指针的大小和内存空间有关。...
  • liutianshx2012
  • liutianshx2012
  • 2016年03月24日 20:37
  • 1249
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:开源:对象运行时大小参考实现(sizeof)
举报原因:
原因补充:

(最多只允许输入30个字)