之前发过一个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)); //第二次计算时就不会 } }
相关推荐
本示例“测量Java对象大小的demo”提供了一种方法,通过使用Java的`java.lang.instrument`包来注入`javaagent`,进而利用`Instrumentation`接口测量Java对象的精确内存占用。下面我们将详细探讨这一过程。 首先,`...
通过`Unsafe`类或`Instrumentation`接口,我们可以获取这些组成部分的具体大小,进而了解一个Java对象在内存中的占用情况。这样的知识对于优化内存使用、排查性能问题和理解JVM内存模型具有重要意义。
你可以编写一个Java代理类,在类加载时获取`Instrumentation`实例,然后调用`getObjectSize()`方法来测量对象大小。例如,使用`PreMain-Class`参数启动Java应用,加载带有`Premain-Class`的代理类。 2. **第三方...
- Java的`java.lang.instrument.Instrumentation`接口提供了获取对象大小的方法。通过代理类或者预加载器(如JDK动态代理或ByteBuddy),可以在运行时获取对象大小。 4. **Memory Profiler**:如YourKit、Eclipse ...
②通过 Class 对象分别获取Constructor类对象、Method类对象 & Field 类对象 ③通过 Constructor类对象、Method类对象 & Field类对象分别获取类的构造函数、方法&属性的具体信息,并进行后续操作 2.3.2 java ...
在Java编程语言中,了解一个对象占用的内存大小是非常重要的,尤其是在优化性能或者处理大量对象时。本示例主要探讨如何测试Java对象占用的内存大小,以便更好地理解内存使用情况。 首先,`SizeOf.java`可能是一个...
在 Java 平台上,`opentelemetry-java-instrumentation` 是一个自动仪器库,它能够自动地对 Java 应用进行监控,无需修改代码即可获取追踪数据。本文将深入探讨 `opentelemetry-java-instrumentation` 的核心概念、...
•• ••适用于Java的OpenTelemetry Instrumentation关于该项目提供了Java代理JAR,该Java代理JAR可以附加到任何Java 8+应用程序,并动态注入字节码以捕获来自许多流行的库和框架的遥测。 您可以采用多种格式导出...
总结起来,利用j-Interop库,Java开发者能够轻松地通过WMI接口获取Windows系统的硬件和性能信息,从而实现更高效、更灵活的系统监控和管理。这在运维自动化、日志收集、性能分析等场景中具有广泛的应用价值。
最后,如果需要获取JAR文件所在的路径(尤其是当程序被打包成JAR时),可以使用`java.lang.instrument.Instrumentation`接口,但这个通常需要在启动时传递特殊参数 `-javaagent` 来启用。不过,在一般应用中,`...
Java Instrumentation API 是 Java 平台标准版(Java SE)的一部分,提供了对正在运行的 Java 应用程序进行动态监视和修改的能力。这包括类加载、字节码操作和代理生成等功能。通过添加代理类(Agent),我们可以...
### Java Instrumentation 深入理解 #### 一、引言 Java Instrumentation 是 Java 平台的一个强大特性,允许开发者在不修改源代码的情况下,动态地修改正在运行的 Java 应用程序的行为。这一特性最早出现在 Java SE...
"ja-netfilter"这个名字暗示了这个框架可能专注于网络数据包过滤,可能是一个利用Java Instrumentation来实现的网络监控和分析工具。在Java中,通过使用`java.lang.instrument`包提供的API,可以实现对网络流量的...
在深入探讨基于java Instrumentation技术的数据采集探针验证之前,让我们先了解一下一些核心概念和技术背景。Java Instrumentation是Java语言提供的一个功能,它允许开发者在Java虚拟机(JVM)加载类之前或之后对类...
在Java编程语言中,获取硬盘序列号是一项常见的需求,特别是在系统信息检测、设备标识或防盗追踪等场景。本文将详细讲解两种不同的方法来实现这一功能。 ### 方法一:使用`Win32_DiskDrive` WMI(Windows ...
Java 获取 CPU 主板硬盘序列号 本文档主要介绍了使用 Java 语言获取 CPU 主板硬盘序列号的方法。该方法通过使用 Java 的 Runtime 类和 Process 类来执行 Windows 脚本(VBScript),从而获取 CPU 主板和硬盘的...
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 ...
总结一下,获取硬盘的序列号、型号、修订号、缓存大小以及物理参数如柱面数、磁头数和扇区数,需要利用操作系统特定的API或者第三方库,如`JDiskSerial`。在Java中,这样的操作往往涉及到JNI,因为标准库并不提供...
这段代码使用 `Runtime` 对象的 `totalMemory()`、`freeMemory()` 方法获取系统的总内存、空闲内存和已用内存,然后将结果输出到控制台。 2. 使用 com.sun.management.OperatingSystemMXBean `...
在Windows环境下,Java可以通过Java Native Interface (JNI) 来调用本地API,如Kernel32.dll中的函数,获取硬件信息,例如CPU型号、内存大小等。例如,可以使用WMI(Windows Management Instrumentation)接口来查询...