我之前在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提供的一个高级API,它允许我们在运行时查看和修改类的字节码。这个接口提供了诸如`getObjectSize()`方法,可以用来获取对象在内存中...
这个例子通常会使用Java内置的`sun.misc.Unsafe`类或者第三方库如`java.lang.instrument.Instrumentation`来计算对象大小。`Unsafe`类提供了访问内存的底层功能,可以获取对象头和实例数据的大小。 在`...
你可以编写一个Java代理类,在类加载时获取`Instrumentation`实例,然后调用`getObjectSize()`方法来测量对象大小。例如,使用`PreMain-Class`参数启动Java应用,加载带有`Premain-Class`的代理类。 2. **第三方...
- Java的`java.lang.instrument.Instrumentation`接口提供了获取对象大小的方法。通过代理类或者预加载器(如JDK动态代理或ByteBuddy),可以在运行时获取对象大小。 4. **Memory Profiler**:如YourKit、Eclipse ...
例如,`sun.misc.Unsafe`类(虽然非标准,但广泛使用)提供了访问内存的能力,包括获取对象大小。然而,需要注意的是,这个类在Java 9及以后的版本中被弃用,并且在某些JRE中可能不可用。 `SizeOfObject.java`可能...
通过上述步骤,我们可以在不使用JNI的情况下,利用Java语言本身的能力获取到系统的CPU使用率及内存使用情况。这种方式不仅简单高效,而且对于开发者的技能要求相对较低,非常适合用于日常的应用程序监控场景。需要...
- `java.util.Vector` 是线程安全的动态数组,可以自动调整大小,适用于多线程环境。 - **栈类 Stack** - `java.util.Stack` 继承自 `Vector`,实现了一个后进先出 (LIFO) 的数据结构。 - **哈希表类 Hashtable*...
在JSP中,你可能需要将这些Java代码封装到一个Servlet或Bean中,然后在JSP页面上调用这些方法,显示获取到的硬件信息。这通常涉及到请求处理、数据传递以及可能的AJAX异步请求。 总结来说,"jsp获取电脑信息控件"这...
在Java中,我们无法直接获取对象的大小,但有一些工具和技巧可以帮助我们进行估算。例如,可以使用`Instrumentation`接口,通过以下步骤获取: 1. 实现`java.lang.instrument.Instrumentation`的代理类。 2. 使用`...
4. **数据结构和对象**:在获取打印机信息时,可能会涉及到一系列数据结构,如打印机队列、作业状态、纸张大小等。理解这些数据结构的含义和使用方式是编写有效代码的关键。 5. **网络打印**:在现代企业环境中,...
12. **获取磁盘空间大小的新方法**:在`java.io.File`类中新增了方法,可以直接获取文件或目录的磁盘空间信息。 这些特性提升了JDK 1.6的综合性能,简化了开发流程,增强了应用程序的可维护性和可扩展性,对于Java...
Java SE(J2SE)是Java平台标准版的简称,它是Java开发环境的基础,提供了丰富的类库和API供开发者使用。以下是对标题和描述中涉及的一些知识点的详细解释: 1. **Desktop类**:`java.awt.Desktop`类允许用户通过...
例如,ManagementObjectSearcher和ManagementObjectCollection类可以用来查询并获取WMI(Windows Management Instrumentation)中的数据,这包括CPU、内存、硬盘、网络适配器等硬件信息。此外,还可能使用了...
开发者可以利用Android Studio的布局编辑器实时预览和调整布局。 "資源檔"一般包括字符串、颜色、尺寸、样式等多种类型,它们存储在`res`目录下的相应子目录中。例如,`res/values`下的`strings.xml`文件用于定义...
这些文件包含了各种视图组件(TextView、Button、ImageView等)及其布局属性,如大小、位置、对齐方式等。 - 可能使用了ConstraintLayout,这是一种灵活的布局管理器,能够适应不同屏幕尺寸,实现响应式设计。 2. ...