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

Java利用Instrumentation获取对象大小升级版

阅读更多

    之前发过一个Java利用Instrumentation获取对象大小的博客,这次修复了一些Bug,应该是非常准确了,除了一种情况,那就是下面代码里面main方法里的情况:

/**
 * 因为要用到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 Map<Object, Object> visited = new IdentityHashMap<Object, Object>();
    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) {
//            // 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;
    }

    public static void main(String[] args) throws Exception
    {
        Object a = new Object();
        Object b = a;
        System.out.println(System.identityHashCode(a) + ":" + System.identityHashCode(b));
        String stra = new String("abc");
        String strb = new String("abc");
        System.out.println("stra : " + fullSizeOf(stra)); //第一次计算时把"abc"这个常量池里面的字符串的字符数组给算进去了
        System.out.println("strb : " + fullSizeOf(strb)); //第二次计算时就不会
    }
}

 

1
4
分享到:
评论

相关推荐

    测量Java对象大小的demo

    本示例“测量Java对象大小的demo”提供了一种方法,通过使用Java的`java.lang.instrument`包来注入`javaagent`,进而利用`Instrumentation`接口测量Java对象的精确内存占用。下面我们将详细探讨这一过程。 首先,`...

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

    通过`Unsafe`类或`Instrumentation`接口,我们可以获取这些组成部分的具体大小,进而了解一个Java对象在内存中的占用情况。这样的知识对于优化内存使用、排查性能问题和理解JVM内存模型具有重要意义。

    java 对象 内存 大小

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

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

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

    Java Instrumentation Framework.rar

    ②通过 Class 对象分别获取Constructor类对象、Method类对象 & Field 类对象 ③通过 Constructor类对象、Method类对象 & Field类对象分别获取类的构造函数、方法&属性的具体信息,并进行后续操作 2.3.2 java ...

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

    在Java编程语言中,了解一个对象占用的内存大小是非常重要的,尤其是在优化性能或者处理大量对象时。本示例主要探讨如何测试Java对象占用的内存大小,以便更好地理解内存使用情况。 首先,`SizeOf.java`可能是一个...

    opentelemetry-java-instrumentation 源码阅读

    在 Java 平台上,`opentelemetry-java-instrumentation` 是一个自动仪器库,它能够自动地对 Java 应用进行监控,无需修改代码即可获取追踪数据。本文将深入探讨 `opentelemetry-java-instrumentation` 的核心概念、...

    opentelemetry-java-instrumentation:适用于Java的OpenTelemetry自动仪器和工具库

    •• ••适用于Java的OpenTelemetry Instrumentation关于该项目提供了Java代理JAR,该Java代理JAR可以附加到任何Java 8+应用程序,并动态注入字节码以捕获来自许多流行的库和框架的遥测。 您可以采用多种格式导出...

    使用j-Interop实现java连接wmi获取windows系统信息的例子

    总结起来,利用j-Interop库,Java开发者能够轻松地通过WMI接口获取Windows系统的硬件和性能信息,从而实现更高效、更灵活的系统监控和管理。这在运维自动化、日志收集、性能分析等场景中具有广泛的应用价值。

    在Java程序中获取当前运行程序的路径

    最后,如果需要获取JAR文件所在的路径(尤其是当程序被打包成JAR时),可以使用`java.lang.instrument.Instrumentation`接口,但这个通常需要在启动时传递特殊参数 `-javaagent` 来启用。不过,在一般应用中,`...

    基于 Java Instrumentation + Javaassist 的简单 RASP.zip

    Java Instrumentation API 是 Java 平台标准版(Java SE)的一部分,提供了对正在运行的 Java 应用程序进行动态监视和修改的能力。这包括类加载、字节码操作和代理生成等功能。通过添加代理类(Agent),我们可以...

    Java Instrumentation笔记

    ### Java Instrumentation 深入理解 #### 一、引言 Java Instrumentation 是 Java 平台的一个强大特性,允许开发者在不修改源代码的情况下,动态地修改正在运行的 Java 应用程序的行为。这一特性最早出现在 Java SE...

    A Java Instrumentation Framework.zip

    "ja-netfilter"这个名字暗示了这个框架可能专注于网络数据包过滤,可能是一个利用Java Instrumentation来实现的网络监控和分析工具。在Java中,通过使用`java.lang.instrument`包提供的API,可以实现对网络流量的...

    基于java Instrumentation技术的数据采集探针验证.pdf

    在深入探讨基于java Instrumentation技术的数据采集探针验证之前,让我们先了解一下一些核心概念和技术背景。Java Instrumentation是Java语言提供的一个功能,它允许开发者在Java虚拟机(JVM)加载类之前或之后对类...

    java获取硬盘序列号的两种方法

    在Java编程语言中,获取硬盘序列号是一项常见的需求,特别是在系统信息检测、设备标识或防盗追踪等场景。本文将详细讲解两种不同的方法来实现这一功能。 ### 方法一:使用`Win32_DiskDrive` WMI(Windows ...

    Java获取CPU主板硬盘序列号.doc

    Java 获取 CPU 主板硬盘序列号 本文档主要介绍了使用 Java 语言获取 CPU 主板硬盘序列号的方法。该方法通过使用 Java 的 Runtime 类和 Process 类来执行 Windows 脚本(VBScript),从而获取 CPU 主板和硬盘的...

    Instrumentation of Java Bytecode for Runtime Analysis

    This paper describes JSpy, a system for high-level instrumentation of Java bytecode and its use with JPaX, our system for runtime analysis of Java programs. JPaX monitors the execution of temporal ...

    java获取硬盘序列号,型号,修订号,缓存大小,柱面数,磁头数,扇区数

    总结一下,获取硬盘的序列号、型号、修订号、缓存大小以及物理参数如柱面数、磁头数和扇区数,需要利用操作系统特定的API或者第三方库,如`JDiskSerial`。在Java中,这样的操作往往涉及到JNI,因为标准库并不提供...

    Java获取系统信息(cpu_内存_硬盘_进程等)的相关方法

    这段代码使用 `Runtime` 对象的 `totalMemory()`、`freeMemory()` 方法获取系统的总内存、空闲内存和已用内存,然后将结果输出到控制台。 2. 使用 com.sun.management.OperatingSystemMXBean `...

    java读取服务器硬件信息(windowx+linux+Mac OS)

    在Windows环境下,Java可以通过Java Native Interface (JNI) 来调用本地API,如Kernel32.dll中的函数,获取硬件信息,例如CPU型号、内存大小等。例如,可以使用WMI(Windows Management Instrumentation)接口来查询...

Global site tag (gtag.js) - Google Analytics