`
teasp
  • 浏览: 61515 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Java利用Instrumentation获取对象大小

阅读更多

    我之前在http://teasp.iteye.com/blog/1870871这里贴出了两种计算Java对象的方式,一种是根据虚拟机实现直接计算,另一种是通过new对象测出来实际大小。前者效率高,但是不通用,而且还是有问题的,后者正确性应该不错,但是效率低。现在又从http://www.jroller.com/maxim/entry/again_about_determining_size_of这里获得了第三种方式,通过Instrumentation计算对象大小,不过根据我的测试,这份代码应该是有bug,希望有感兴趣的童鞋能一起来研究下:

/**
 * 因为要用到java.lang.instrument.Instrumentation,
 * 本代码需要打成jar包以javaagent运行,manifest.mf文件内容如下
   Manifest-Version: 1.0
   Premain-Class: com.teasp.mem.SizeOfAgent
   Boot-Class-Path: 
   Can-Redefine-Classes: false
 * 运行方式:打包成sizeof.jar后,
 * 执行java -javaagent:sizeof.jar com.teasp.mem.SizeOfAgent
 */
public class SizeOfAgent
{
    private 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) {//这个if是bug,应当去掉--teasp
            // skip interned string
            if (obj == ((String) obj).intern()) {
                return true;
            }
        }
        return (obj == null) || visited.containsKey(obj);
    }
  
    @SuppressWarnings("rawtypes")
    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++) 
                {
                    stack.add(Array.get(obj, i));
                } 
            }       
            return result;
        }
                  
        // process all fields of the object
        while (clazz != null) 
        {
            Field[] fields = clazz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) 
            {
                if (!Modifier.isStatic(fields[i].getModifiers())) 
                {
                    if (fields[i].getType().isPrimitive()) 
                    {
                        continue; // skip primitive fields
                    } 
                    else 
                    {
                        fields[i].setAccessible(true);
                        try 
                        {
                            // objects to be estimated are put to stack
                            Object objectToAdd = fields[i].get(obj);
                            if (objectToAdd != null) 
                            {                        
                                stack.add(objectToAdd);
                            }
                        } 
                        catch (IllegalAccessException ex) 
                        { 
                            assert false; 
                        }
                    }
                }
            }
            clazz = clazz.getSuperclass();
        }
        return result;
    }

    static Obj4SizeofTest obj = new Obj4SizeofTest();
    public static void main(String[] args) throws Exception
    {
        System.out.println("fullSizeOf : " + fullSizeOf(new Obj4SizeofTest()));
        System.out.println("sizeOf : " + sizeOf(new Obj4SizeofTest()));
        System.out.println("sizeOf Integer: " + sizeOf(new Integer(0)));
        System.out.println("sizeOf Object: " + sizeOf(new Object()));
        
        System.out.println("fullSizeOf Son: " + fullSizeOf(new Son()));
        
        System.out.println("fullSizeOf WierdStringSon: " + fullSizeOf(new WierdStringSon()));
        System.out.println("fullSizeOf WierdString: " + fullSizeOf(new WierdString()));
        
        System.out.println("HotspotSizeof Obj4SizeofTest : " + HotspotSizeof.sizeof(new Obj4SizeofTest()));
        System.out.println("determinObjSize Obj4SizeofTest : " + HotspotSizeof.determinObjSize(Obj4SizeofTest.class));
    }
}

HotspotSizeof.java见http://teasp.iteye.com/blog/1870871

 

下面是测试用到的一些类:

public class Papa
{
    int aint = 4;
    public static int bint;
//    private String str = "123";
//    private String str = new String("123");
    String str = new String(new byte[]{49,50,51});
//    private String str = new String(new char[]{49,50,51});
    int[] ints = {};
//    private int[][] intss = {{}};
    int[][] intss = {{1},{1,2}};
    
    protected float getNum()
    {
        return 4.0f;
    }
}

public class Obj4SizeofTest extends Papa implements Type
{
    int aint = 3;
    public int bint = 4;
    boolean b1 = true;
    boolean b2 = true;
    boolean b3 = true;
    boolean b4 = true;
    boolean b5 = true;
    boolean b6 = true;
    boolean b7 = true;
    boolean b8 = true;
    String str1;
    Object obj = new Papa();
    public static final byte[] bytes = {97};
    String str2 = new String(bytes);
    Integer i = new Integer(1);
    int[] is = {1,2,3};
    Object[][] objs = {{new Object(),new Object()},{new Object(),new Object()}};
        
    private static class Inner 
    {}
    
    private class Inner1
    {}
}

public class Father
{
    byte f;
}

public class Son extends Father
{
    byte s;
}

public class WierdString
{
    String str = new String(new byte[]{49,50,51});
}

public class WierdStringSon extends WierdString
{
    byte b1;
}

 

1
3
分享到:
评论

相关推荐

    测量Java对象大小的demo

    在本案例中,`javaagent`被用来获取对象大小信息。 `Instrumentation`接口是Java提供的一个高级API,它允许我们在运行时查看和修改类的字节码。这个接口提供了诸如`getObjectSize()`方法,可以用来获取对象在内存中...

    JAVA对象所占内存大小计算例子

    这个例子通常会使用Java内置的`sun.misc.Unsafe`类或者第三方库如`java.lang.instrument.Instrumentation`来计算对象大小。`Unsafe`类提供了访问内存的底层功能,可以获取对象头和实例数据的大小。 在`...

    java 对象 内存 大小

    你可以编写一个Java代理类,在类加载时获取`Instrumentation`实例,然后调用`getObjectSize()`方法来测量对象大小。例如,使用`PreMain-Class`参数启动Java应用,加载带有`Premain-Class`的代理类。 2. **第三方...

    统计缓存(java对象所占的内存)大小

    - Java的`java.lang.instrument.Instrumentation`接口提供了获取对象大小的方法。通过代理类或者预加载器(如JDK动态代理或ByteBuddy),可以在运行时获取对象大小。 4. **Memory Profiler**:如YourKit、Eclipse ...

    测试java对象占用内存大小的例子

    例如,`sun.misc.Unsafe`类(虽然非标准,但广泛使用)提供了访问内存的能力,包括获取对象大小。然而,需要注意的是,这个类在Java 9及以后的版本中被弃用,并且在某些JRE中可能不可用。 `SizeOfObject.java`可能...

    java获得CPU使用率.doc

    通过上述步骤,我们可以在不使用JNI的情况下,利用Java语言本身的能力获取到系统的CPU使用率及内存使用情况。这种方式不仅简单高效,而且对于开发者的技能要求相对较低,非常适合用于日常的应用程序监控场景。需要...

    (超赞)JAVA精华之--深入JAVA API

    - `java.util.Vector` 是线程安全的动态数组,可以自动调整大小,适用于多线程环境。 - **栈类 Stack** - `java.util.Stack` 继承自 `Vector`,实现了一个后进先出 (LIFO) 的数据结构。 - **哈希表类 Hashtable*...

    jsp获取电脑信息控件

    在JSP中,你可能需要将这些Java代码封装到一个Servlet或Bean中,然后在JSP页面上调用这些方法,显示获取到的硬件信息。这通常涉及到请求处理、数据传递以及可能的AJAX异步请求。 总结来说,"jsp获取电脑信息控件"这...

    java-object-size

    在Java中,我们无法直接获取对象的大小,但有一些工具和技巧可以帮助我们进行估算。例如,可以使用`Instrumentation`接口,通过以下步骤获取: 1. 实现`java.lang.instrument.Instrumentation`的代理类。 2. 使用`...

    计算机软件-商业源码-实例53 获取打印机信息.zip

    4. **数据结构和对象**:在获取打印机信息时,可能会涉及到一系列数据结构,如打印机队列、作业状态、纸张大小等。理解这些数据结构的含义和使用方式是编写有效代码的关键。 5. **网络打印**:在现代企业环境中,...

    JDK1.6新特性说明.doc

    12. **获取磁盘空间大小的新方法**:在`java.io.File`类中新增了方法,可以直接获取文件或目录的磁盘空间信息。 这些特性提升了JDK 1.6的综合性能,简化了开发流程,增强了应用程序的可维护性和可扩展性,对于Java...

    j2se一句话学习笔记

    Java SE(J2SE)是Java平台标准版的简称,它是Java开发环境的基础,提供了丰富的类库和API供开发者使用。以下是对标题和描述中涉及的一些知识点的详细解释: 1. **Desktop类**:`java.awt.Desktop`类允许用户通过...

    系统与文件查看器

    例如,ManagementObjectSearcher和ManagementObjectCollection类可以用来查询并获取WMI(Windows Management Instrumentation)中的数据,这包括CPU、内存、硬盘、网络适配器等硬件信息。此外,还可能使用了...

    android test

    开发者可以利用Android Studio的布局编辑器实时预览和调整布局。 "資源檔"一般包括字符串、颜色、尺寸、样式等多种类型,它们存储在`res`目录下的相应子目录中。例如,`res/values`下的`strings.xml`文件用于定义...

    AndroidStudio_CoffeeShop

    这些文件包含了各种视图组件(TextView、Button、ImageView等)及其布局属性,如大小、位置、对齐方式等。 - 可能使用了ConstraintLayout,这是一种灵活的布局管理器,能够适应不同屏幕尺寸,实现响应式设计。 2. ...

Global site tag (gtag.js) - Google Analytics