当前位置:编程学习 > JAVA >>

如何查看java对象所占的内存大小

我们为什么想要知道对象所占对内存的大小呢?

(1)做一些cache的时候,我们不可能把数据库的所有的数据都缓存到内存里面,我们要估计缓存的大小。
(2)内存泄露的时候,我们可以查看某些对象的大小来定位问题,当然还有其他的更有效的方式,比如使用MAT分析dump文件
(3)根据jvm的堆内存设置,我们可以知道最多可以创建多少个对象。
从jdk5开始,提供了Instrumentation API,它有一个叫做getObjectSize()的方法,但是,这个方法存在两个问题:
(1)不可以直接使用。必须要实现一个Instrumentation Agent,还得放到jar包里面。
(2)它只能返回单个对象的大小,不能返回内部包含的子对象的大小。
关于第一个问题,很好解决,在任何一个类里面声明一个"premain"方法,就可以把这个类做成是一个agent:
public class SizeOfAgent {
         static Instrumentation inst;
         /** initializes agent */
         public static void premain(String agentArgs, Instrumentation instP) {
                 inst = instP;          
         }
 }
jvm在启动的时候会调用premain()方法,同时会传递Instrumentation这个对象实例,要告诉jvm Instrumentation agent所在的类,需要把这个类打到jar包里面,
然后在manifest.mf这个文件设置一些属性:
Premain-Class: sizeof.agent.SizeOfAgent
Boot-Class-Path:
Can-Redefine-Classes: false
java应用在启动的时候,指定-javaagent参数:
java -javaagent:sizeofag.jar <Your main class>
拿到Instrumentation这个实例以后,就可以调用sizeOf()方法了:
public class SizeOfAgent {
         static Instrumentation inst;
         // ...
         public static long sizeOf(Object o) {
                 return inst.getObjectSize(o);
         }
 }
然后可以使用反射来获取子对象的大小。
完整的代码如下:
package com.bj58.test;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Stack;
public class SizeOfAgent {
    static Instrumentation inst;
    /** initializes agent */
    public static void premain(String agentArgs, Instrumentation instP) {
        inst = instP;
    }

    /**
     * Returns object size without member sub-objects.
     *
     * @param o
     *            object to get size of
     * @return object size
     */
    public static long sizeOf(Object o) {
        if (inst == null) {
            throw new IllegalStateException(
                    "Can not access instrumentation environment.\n"
                            + "Please check if jar file containing SizeOfAgent class is \n"
                            + "specified in the java's \"-javaagent\" command line argument.");
        }
        return inst.getObjectSize(o);
    }

    /**
     * Calculates full size of object iterating over its hierarchy graph.
     *
     * @param obj
     *            object to calculate size of
     * @return object size
     */
    public static long fullSizeOf(Object obj) {
        Map<Object, Object> visited = new IdentityHashMap<Object, Object>();
        Stack<Object> stack = new Stack<Object>();
        long result = internalSizeOf(obj, stack, visited);
        while (!stack.isEmpty()) {
            result += internalSizeOf(stack.pop(), stack, visited);
        }
        visited.clear();
        return result;
    }

    private static boolean skipObject(Object obj, Map<Object, Object> visited) {
        if (obj instanceof String) {
            // skip interned string
            if (obj == ((String) obj).intern()) {
                return true;
            }
        }
        return (obj == null) // skip visited object
                || visited.containsKey(obj);
    }

    private static long internalSizeOf(Object obj, Stack<Object> stack,
            Map<Object, Object> visited) {
        if (skipObject(obj, visited)) {
            return 0;
        }
        visited.put(obj, null);
        long result = 0;
        // get size of object + primitive variables + member pointers
        result += SizeOfAgent.sizeOf(obj);
        // process all array elements
        Class clazz = obj.getClass();
        if (clazz.isArray()) {
            if (clazz.getName().length() != 2) {// skip primitive type array
                int length = Array.getLength(obj);
                for (int i = 0; i < length; i++) {
                &nbs

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,