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

于是发现了这么个东西:

wKiom1QH-Q6ieB0DAAHo9yLcc9U558.jpg



光看了下该方法的声明,这不就是获取对象的大小么,于是没想太多,心想这下问题变得简单了,弄了个premain方法初始化Instrumentation:

    public class ObjectSizeUtils {

    private static Instrumentation inst = null;

    public static void premain(String agentArgs, Instrumentation inst) {
        ObjectSizeUtils.inst = inst;
    }

    public static long sizeOf(Object o){
        if(inst == null) throw new IllegalStateException("not initialized yet");
        return inst.getObjectSize(o);
    }
}


export jar并在MANIFEST.MF中加上:

Premain-class: pac.testcase.utils.ObjectSizeUtils
Can-Redefine-Classes: false


随便写一个实体类,用来测试:

class Person{
    private  String name;
    private String life;

    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public String getLife() {return life;}
    public void setLife(String life) {this.life = life;}
}



好了,在运行参数中加上-javaagent,执行看看会输出什么:

    @Test
    public void testSizeUtils(){
        Person person = new Person("Alvez","make me death before you make me old");
        logger.info(String.valueOf(sizeOf(person)));
        logger.info(String.valueOf(sizeOf(person.getName())));
        logger.info(String.valueOf(sizeOf(person.getLife())));
    }

    static final Logger logger = LoggerFactory.getLogger(ObjectSizeUtils.class);


结果....

wKiom1QIARLjYjPyAACmhy1CJkY720.jpg



为什么person的属性比person还大? 等等,name和life的大小好像也有问题....

回去翻教科书发现事情并不是我希望的那样,我需要把对象里面的元素的大小全部加起来才能达到我要的效果....

看来还需要亲自解决一些事情,于是:

public class ObjectSizeUtils {

    private static Instrumentation inst = null;

    public static void premain(String agentArgs, Instrumentation inst) {
        ObjectSizeUtils.inst = inst;
    }

    public static long sizeOf(Object o) throws IllegalAccessException {
    if(inst == null) throw new IllegalStateException("not initialized yet");
        SizeCounter sizeCounter = new SizeCounter();
        sizeOf(o, sizeCounter);
        return sizeCounter.getSize();
    }

    public static void sizeOf(Object o,SizeCounter sizeCounter) throws IllegalAccessException {
        if(o!=null){
            sizeCounter.addSize(inst.getObjectSize(o));
            Class c = o.getClass();
            Field[] fields = c.getDeclaredFields();
            for (Field f : fields) {
                int mod = f.getModifiers();
                if(Modifier.isStatic(mod) || f.getType().isPrimitive()){
                    continue;
                }
                f.setAccessible(true);
                Object o1 = f.get(o);
                sizeOf(o1,sizeCounter);
            }
        }
    }
    
}

class SizeCounter{
        private long size;

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }

    public void addSize(long size){
        this.setSize(this.getSize() + size);
    }
}



这段代码并不完整,还有很多因素并没有考虑进去,大体思路差不多就是这样。