有没有一种简单的方法来获取java对象的大小?

有没有一种简单的方法来获取java对象的大小?,java,Java,我想知道检索java对象大小的简单方法?此外,无论如何,在C++中,如sisiof操作符的大小, 有一个决定内存中任何java对象的大小。 接口有一个GETObjsisiZE()方法。 但是,这仅提供对象本身的大小,而不提供其组件子对象的大小。例如,它会告诉您所有String对象的大小都相同 另一个问题是对象的大小实际上可以自发地改变。例如,如果您获得一个对象的标识hashcode,并且它在GC循环中存活,那么它的大小将增加(至少)4个字节以存储标识hashcode值 查找“对象”大小的问题在

我想知道检索java对象大小的简单方法?此外,无论如何,在C++中,如sisiof操作符的大小,

有一个决定内存中任何java对象的大小。

接口有一个GETObjsisiZE()方法。 但是,这仅提供对象本身的大小,而不提供其组件子对象的大小。例如,它会告诉您所有
String
对象的大小都相同

另一个问题是对象的大小实际上可以自发地改变。例如,如果您获得一个对象的标识hashcode,并且它在GC循环中存活,那么它的大小将增加(至少)4个字节以存储标识hashcode值


查找“对象”大小的问题在于,一般实用程序类/方法不可能确切知道任意对象的抽象边界在哪里。即使像String类这样简单的东西也存在问题。(考虑在Java 6中使用
子字符串(…)
创建的字符串对象。是否可以将
char[]value
对象作为
的一部分,或者作为原始字符串的一部分,或者两者兼而有之?这对相应对象的大小意味着什么?)


因此,像
net.sourceforge.sizeof
这样的东西无法完全准确地计算空间使用情况,这是不可避免的。

当程序运行时,获取另一个终端窗口并运行:

jmap -histo <process id of the java instance you want to debug>
然后打开。您可以在浏览器中浏览堆上的对象

更多信息:



顺便说一句,我认为在Sun/Oracle JVM上,它总是四舍五入到8,即使对象是12个字节,也需要16个内存。

使用
Sun.misc
中的
safe
类,可以获得字段偏移量。因此,根据处理器体系结构考虑对象堆对齐并计算最大字段偏移量,您可以测量Java对象的大小。在下面的示例中,我使用辅助类
UtilUnsafe
获取对
sun.misc.Unsafe
对象的引用

private static final int NR_BITS = Integer.valueOf(System.getProperty("sun.arch.data.model"));
private static final int BYTE = 8;
private static final int WORD = NR_BITS/BYTE;
private static final int MIN_SIZE = 16; 

public static int sizeOf(Class src){
    //
    // Get the instance fields of src class
    // 
    List<Field> instanceFields = new LinkedList<Field>();
    do{
        if(src == Object.class) return MIN_SIZE;
        for (Field f : src.getDeclaredFields()) {
            if((f.getModifiers() & Modifier.STATIC) == 0){
                instanceFields.add(f);
            }
        }
        src = src.getSuperclass();
    }while(instanceFields.isEmpty());
    //
    // Get the field with the maximum offset
    //  
    long maxOffset = 0;
    for (Field f : instanceFields) {
        long offset = UtilUnsafe.UNSAFE.objectFieldOffset(f);
        if(offset > maxOffset) maxOffset = offset; 
    }
    return  (((int)maxOffset/WORD) + 1)*WORD; 
}
class UtilUnsafe {
    public static final sun.misc.Unsafe UNSAFE;

    static {
        Object theUnsafe = null;
        Exception exception = null;
        try {
            Class<?> uc = Class.forName("sun.misc.Unsafe");
            Field f = uc.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            theUnsafe = f.get(uc);
        } catch (Exception e) { exception = e; }
        UNSAFE = (sun.misc.Unsafe) theUnsafe;
        if (UNSAFE == null) throw new Error("Could not obtain access to sun.misc.Unsafe", exception);
    }
    private UtilUnsafe() { }
}
private static final int NR_BITS=Integer.valueOf(System.getProperty(“sun.arch.data.model”);
专用静态最终整数字节=8;
专用静态最终整数字=NR_位/字节;
专用静态最终整数最小值=16;
公共静态int-sizeOf(类src){
//
//获取src类的实例字段
// 
List instanceFields=new LinkedList();
做{
if(src==Object.class)返回最小大小;
for(字段f:src.getDeclaredFields()){
if((f.getModifiers()&Modifier.STATIC)==0){
instanceFields.add(f);
}
}
src=src.getSuperclass();
}while(instanceFields.isEmpty());
//
//获取具有最大偏移量的字段
//  
长最大偏移量=0;
用于(字段f:instanceFields){
长偏移量=UtilUnsafe.UNSAFE.objectFieldOffset(f);
如果(偏移>最大偏移)最大偏移=偏移;
}
返回(((int)最大偏移量/字)+1)*字;
}
类UtilUnsafe{
公共静态最终sun.misc.Unsafe;
静止的{
Object=null;
异常=空;
试一试{
类uc=类forName(“sun.misc.Unsafe”);
字段f=uc.getDeclaredField(“不安全”);
f、 setAccessible(true);
不安全=f.get(uc);
}catch(异常e){Exception=e;}
不安全=(sun.misc.UNSAFE)不安全;
if(UNSAFE==null)抛出新错误(“无法访问sun.misc.UNSAFE”,异常);
}
私有UtilUnsafe(){}
}

获取对象大小绝对是可能的,因为某个类的对象只是一个固定大小的内存块。我编写了以下代码来计算对象的保留大小。它还提供了一种类似于C++中的“sieof”的方法。它已经准备好运行,不依赖任何东西。你可以复制并试用它

public class ObjectSizer {

    public static final Unsafe us = getUnsafe();

    public static boolean useCompressedOops = true;

    public static int retainedSize(Object obj) {
        return retainedSize(obj, new HashMap<Object, Object>());
    }

    private static int retainedSize(Object obj, HashMap<Object, Object> calculated) {
        try {
            if (obj == null)
                throw new NullPointerException();
            calculated.put(obj, obj);
            Class<?> cls = obj.getClass();
            if (cls.isArray()) {
                int arraysize = us.arrayBaseOffset(cls) + us.arrayIndexScale(cls) * Array.getLength(obj);
                if (!cls.getComponentType().isPrimitive()) {
                    Object[] arr = (Object[]) obj;
                    for (Object comp : arr) {
                        if (comp != null && !isCalculated(calculated, comp))
                            arraysize += retainedSize(comp, calculated);
                    }
                }
                return arraysize;
            } else {
                int objectsize = sizeof(cls);
                for (Field f : getAllNonStaticFields(obj.getClass())) {
                    Class<?> fcls = f.getType();
                    if (fcls.isPrimitive())
                        continue;
                    f.setAccessible(true);
                    Object ref = f.get(obj);
                    if (ref != null && !isCalculated(calculated, ref)) {
                        int referentSize = retainedSize(ref, calculated);
                        objectsize += referentSize;
                    }
                }
                return objectsize;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static int sizeof(Class<?> cls) {

        if (cls == null)
            throw new NullPointerException();

        if (cls.isArray())
            throw new IllegalArgumentException();

        if (cls.isPrimitive())
            return primsize(cls);

        int lastOffset = Integer.MIN_VALUE;
        Class<?> lastClass = null;

        for (Field f : getAllNonStaticFields(cls)) {
            if (Modifier.isStatic(f.getModifiers()))
                continue;

            int offset = (int) us.objectFieldOffset(f);
            if (offset > lastOffset) {
                lastOffset = offset;
                lastClass = f.getClass();
            }
        }
        if (lastOffset > 0)
            return modulo8(lastOffset + primsize(lastClass));
        else
            return 16;
    }

    private static Field[] getAllNonStaticFields(Class<?> cls) {
        if (cls == null)
            throw new NullPointerException();

        List<Field> fieldList = new ArrayList<Field>();
        while (cls != Object.class) {
            for (Field f : cls.getDeclaredFields()) {
                if (!Modifier.isStatic(f.getModifiers()))
                    fieldList.add(f);
            }
            cls = cls.getSuperclass();
        }
        Field[] fs = new Field[fieldList.size()];
        fieldList.toArray(fs);
        return fs;
    }

    private static boolean isCalculated(HashMap<Object, Object> calculated, Object test) {
        Object that = calculated.get(test);
        return that != null && that == test;
    }

    private static int primsize(Class<?> cls) {
        if (cls == byte.class)
            return 1;
        if (cls == boolean.class)
            return 1;
        if (cls == char.class)
            return 2;
        if (cls == short.class)
            return 2;
        if (cls == int.class)
            return 4;
        if (cls == float.class)
            return 4;
        if (cls == long.class)
            return 8;
        if (cls == double.class)
            return 8;
        else
            return useCompressedOops ? 4 : 8;
    }

    private static int modulo8(int value) {
        return (value & 0x7) > 0 ? (value & ~0x7) + 8 : value;
    }

    private static Unsafe getUnsafe() {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            return (Unsafe) f.get(Unsafe.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        System.out.println(retainedSize("Hello Leeeeeeeen"));
    }
}
公共类ObjectSizer{
public static final Unsafe us=getUnsafe();
公共静态布尔useCompressedOops=true;
公共静态int-retainedSize(对象obj){
返回retainedSize(obj,newhashMap());
}
私有静态int retainedSize(对象对象对象,HashMap计算){
试一试{
if(obj==null)
抛出新的NullPointerException();
已计算。放置(obj,obj);
类cls=obj.getClass();
if(cls.isArray()){
int arraysize=us.arrayBaseOffset(cls)+us.arrayIndexScale(cls)*Array.getLength(obj);
如果(!cls.getComponentType().isPrimitive()){
Object[]arr=(Object[])obj;
用于(对象组件:arr){
如果(comp!=null&&!已计算(已计算,comp))
arraysize+=保留大小(comp,计算);
}
}
返回阵列化;
}否则{
int objectsize=sizeof(cls);
for(字段f:getAllNonStaticFields(obj.getClass())){
类fcls=f.getType();
if(fcls.isPrimitive())
继续;
f、 setAccessible(true);
对象引用=f.get(obj);
如果(ref!=null&&!已计算(已计算,ref)){
int referencetsize=保留大小(ref,计算);
objectsize+=referentSize;
}
}
返回对象大小;
}
}捕获(例外e){
抛出新的运行时异常(e);
}
}
公共静态int-sizeof(类cls){
如果(cls==null)
抛出新的NullPointerException();
if(cls.isArray())
抛出新的IllegalArgumentException();
如果(cls.isPri
public class ObjectSizer {

    public static final Unsafe us = getUnsafe();

    public static boolean useCompressedOops = true;

    public static int retainedSize(Object obj) {
        return retainedSize(obj, new HashMap<Object, Object>());
    }

    private static int retainedSize(Object obj, HashMap<Object, Object> calculated) {
        try {
            if (obj == null)
                throw new NullPointerException();
            calculated.put(obj, obj);
            Class<?> cls = obj.getClass();
            if (cls.isArray()) {
                int arraysize = us.arrayBaseOffset(cls) + us.arrayIndexScale(cls) * Array.getLength(obj);
                if (!cls.getComponentType().isPrimitive()) {
                    Object[] arr = (Object[]) obj;
                    for (Object comp : arr) {
                        if (comp != null && !isCalculated(calculated, comp))
                            arraysize += retainedSize(comp, calculated);
                    }
                }
                return arraysize;
            } else {
                int objectsize = sizeof(cls);
                for (Field f : getAllNonStaticFields(obj.getClass())) {
                    Class<?> fcls = f.getType();
                    if (fcls.isPrimitive())
                        continue;
                    f.setAccessible(true);
                    Object ref = f.get(obj);
                    if (ref != null && !isCalculated(calculated, ref)) {
                        int referentSize = retainedSize(ref, calculated);
                        objectsize += referentSize;
                    }
                }
                return objectsize;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static int sizeof(Class<?> cls) {

        if (cls == null)
            throw new NullPointerException();

        if (cls.isArray())
            throw new IllegalArgumentException();

        if (cls.isPrimitive())
            return primsize(cls);

        int lastOffset = Integer.MIN_VALUE;
        Class<?> lastClass = null;

        for (Field f : getAllNonStaticFields(cls)) {
            if (Modifier.isStatic(f.getModifiers()))
                continue;

            int offset = (int) us.objectFieldOffset(f);
            if (offset > lastOffset) {
                lastOffset = offset;
                lastClass = f.getClass();
            }
        }
        if (lastOffset > 0)
            return modulo8(lastOffset + primsize(lastClass));
        else
            return 16;
    }

    private static Field[] getAllNonStaticFields(Class<?> cls) {
        if (cls == null)
            throw new NullPointerException();

        List<Field> fieldList = new ArrayList<Field>();
        while (cls != Object.class) {
            for (Field f : cls.getDeclaredFields()) {
                if (!Modifier.isStatic(f.getModifiers()))
                    fieldList.add(f);
            }
            cls = cls.getSuperclass();
        }
        Field[] fs = new Field[fieldList.size()];
        fieldList.toArray(fs);
        return fs;
    }

    private static boolean isCalculated(HashMap<Object, Object> calculated, Object test) {
        Object that = calculated.get(test);
        return that != null && that == test;
    }

    private static int primsize(Class<?> cls) {
        if (cls == byte.class)
            return 1;
        if (cls == boolean.class)
            return 1;
        if (cls == char.class)
            return 2;
        if (cls == short.class)
            return 2;
        if (cls == int.class)
            return 4;
        if (cls == float.class)
            return 4;
        if (cls == long.class)
            return 8;
        if (cls == double.class)
            return 8;
        else
            return useCompressedOops ? 4 : 8;
    }

    private static int modulo8(int value) {
        return (value & 0x7) > 0 ? (value & ~0x7) + 8 : value;
    }

    private static Unsafe getUnsafe() {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);
            return (Unsafe) f.get(Unsafe.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        System.out.println(retainedSize("Hello Leeeeeeeen"));
    }
}