我之前在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; }
相关推荐
注入javaagent使用Instrumentation测量Java对象的大小
Java SE 6新特性:Instrumentation,利用 Java 代码,即 java.lang.instrument 做动态 Instrumentation 是 Java SE 5 的新特性,它把 Java 的 instrument 功能从本地代码中解放出来,使之可以用 Java 代码的方式解决...
②通过 Class 对象分别获取Constructor类对象、Method类对象 & Field 类对象 ③通过 Constructor类对象、Method类对象 & Field类对象分别获取类的构造函数、方法&属性的具体信息,并进行后续操作 2.3.2 java ...
opentelemetry-java-instrumentation 源码阅读
•• ••适用于Java的OpenTelemetry Instrumentation关于该项目提供了Java代理JAR,该Java代理JAR可以附加到任何Java 8+应用程序,并动态注入字节码以捕获来自许多流行的库和框架的遥测。 您可以采用多种格式导出...
A Java Instrumentation Framework.zip
基于 Java Instrumentation + Javaassist 的简单 RASP
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 Instrumentation技术的数据采集探针验证.pdf
java8流源码CS474 - 课程项目 团队成员 迈特雷伊·拉贾戈帕兰 雪莉·马修·乔治 概述 本项目的要求是: 一个检测程序,它采用一些 Java 应用程序的语法正确的源代码,并使用 Eclipse Java 抽象语法树 (AST) 解析器将...
这几天在物流大赛上也用了不少时间,所以对于android的单元测试没有太深入的研究,所以先写个基本入门吧!首先,我们来了解一下android的测试类的层次结构:可以看出android中的测试方法主要有AndroidTextCase和...
java动态编译java源文件,并利用Instrumentation实现重定义class
Instrumentation可以把测试包和目标测试应用加载到同一个进程中运行。既然各个控件和测试代码都运行在同一个进程中了,测试代码当然就可以调用这些控件的方法了,同时修改和验证这些控件的一些数据
Iocomp.Instrumentation.WF40.Common.dll,Iocomp.Instrumentation.WF40.Pro Iocomp.WF40.OPC
Qt5案例之利用QProcess获取计算机硬件信息,介绍利用QProcess获取计算机的CPU、主板、硬盘等电脑相关硬件信息。windows提供了“wmic”(Windows Management Instrumentation,Windows管理工具),提供了从命令行接口...
1 JAVA SE 1.1 深入JAVA API 1.1.1 Lang包 1.1.2 集合类 1.1.2.1.1 日期类Date 1.1.2.1.2 日历类Calendar 1.1.2.1.3 随机数类Random 1.1.2.1.4 向量类Vector 1.1.2.1.5 栈类Stack 1.1.2.1.6 哈希表类Hashtable ...
使用instrumentation创建测试用例示例代码
基础 Java 检测 启动一个基本的检测代理,它将提供 JVM 中特定方法的计时。 将使用当前的 Splunk API 将数据推送到 Splunk。 大量借用 Damien Dallimore 的 SplunkJavaAgent(嗯,它会),利用 SplunkLogEvent 和...
Product Description This title presents the general principles of instrumentation processes. It explains the theoretical analysis of physical phenomena used by standard sensors and transducers to ...
参考博客 【Android中Hook Instrumentation 的实现】 http://blog.csdn.net/u012341052/article/details/71191409