Java 如何查找对象';s大小(包括包含的对象)

Java 如何查找对象';s大小(包括包含的对象),java,object,memory,size,Java,Object,Memory,Size,我想估计一个物体的大小。 要获得对象的大小,我可以使用 为此,我可能会使用Instrumentation.getObjectSize(myObject),但这会给我一个“浅”的大小。我想得到对象的大小,包括它引用的对象的大小 我的想法是,我需要得到对象的大小,然后遍历对象的所有字段,这些字段不是静态的或基本的,然后得到它们指向的对象的大小,并递归地执行此操作 当然,我不想数数一个对象的大小几次,或者陷入循环,所以我必须记住我们已经计算过的对象的大小 有没有更快、更标准的方法 我的代码如下所示:

我想估计一个物体的大小。 要获得对象的大小,我可以使用

为此,我可能会使用
Instrumentation.getObjectSize(myObject)
,但这会给我一个“浅”的大小。我想得到对象的大小,包括它引用的对象的大小

我的想法是,我需要得到对象的大小,然后遍历对象的所有字段,这些字段不是静态的或基本的,然后得到它们指向的对象的大小,并递归地执行此操作

当然,我不想数数一个对象的大小几次,或者陷入循环,所以我必须记住我们已经计算过的对象的大小

有没有更快、更标准的方法

我的代码如下所示:

public static long getObjectSize(Object obj)
{
    return getObjectSize(obj, new HashSet<Object>());
}

private static long getObjectSize(Object obj, Set<Object> encountered)
{
    if (encountered.contains(obj))
    {
        // if this object was already counted - don't count it again
        return 0;
    }
    else
    {
        // remember to not count this object's size again
        encountered.add(obj);
    }
    java.lang.reflect.Field fields[] = obj.getClass().getFields();
    long size = Instrumentation.getObjectSize(obj);
    // itereate through all fields               
    for (Field field : fields)
    {
        Class fieldType = field.getType();
        // only if the field isn't a primitive
         if (fieldType != Boolean.class &&
             fieldType != Integer.class &&
             fieldType != Long.class &&
             fieldType != Float.class &&
             fieldType != Character.class &&
             fieldType != Short.class &&
             fieldType != Double.class)
         {
             // get the field's value
             try
             {
                 Object fieldValue = field.get(obj);
                 size += getObjectSize(obj, encountered);
             } 
             catch (IllegalAccessException e) {}
         }
    }
    return size;
}
publicstaticlong-getObjectSize(objectobj)
{
返回getObjectSize(obj,newHashSet());
}
私有静态long getObjectSize(对象对象,遇到集合)
{
如果(遇到。包含(obj))
{
//如果此对象已计数-不要再次计数
返回0;
}
其他的
{
//记住不要再次计算此对象的大小
添加(obj);
}
java.lang.reflect.fields[]=obj.getClass().getFields();
long size=Instrumentation.getObjectSize(obj);
//在所有字段中创建
用于(字段:字段)
{
类fieldType=field.getType();
//仅当字段不是基元时
if(fieldType!=Boolean.class&&
fieldType!=Integer.class&&
fieldType!=Long.class&&
fieldType!=Float.class&&
fieldType!=Character.class&&
fieldType!=Short.class&&
fieldType!=Double.class)
{
//获取字段的值
尝试
{
对象字段值=field.get(obj);
size+=getObjectSize(obj,遇到);
} 
捕获(非法访问例外){}
}
}
返回大小;
}

尝试序列化对象,然后获取序列化生成的字节流的大小。如果您想知道持久化时对象的大小

 public static byte[] serialize(Object obj) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(obj);
    return baos.toByteArray();
}

这是推荐的做法吗?有替代方法吗?我认为这是最准确的方法,因为序列化是对象结构的字节/字节表示,在最坏的情况下,它会告诉您一个比实际大小稍大的大小,但不会更小,这可能会导致大小限制问题(与其超过它,不如留一些空间)。您还可以添加“浅”对象大小(通过instrumentation类获得的大小),以了解加载到RAM中的对象的总大小,这当然会使每个基本对象的大小增加一倍,因为它们本身就是对自身值的引用。