Java计算一个对象占用内存的大小
来源:互联网 发布:2组数据相关性分析 编辑:程序博客网 时间:2024/05/17 22:45
在C/C++中计算某一个基本类型或者对象占用内存大小的方法很简单,只要调用库里面的sizeof()操作符即可,但是在Java的API里面并没有给我们提供类似的方法。那么我们可不可以自己实现一个Java中的sizeof()方法呢?答案是肯定的。为了计算一个Java对象占用内存的大小,首先你得对Java对象的内存结构有所了解。如果你还不了解,请先阅读Java内存结构。
首先介绍一下sun.misc.Unsafe类,该类是Java中很神奇的一个类,这个类是用于执行低级别、不安全操作的方法集合。尽管这个类和所有的方法都是公开的(public),但是这个类的使用仍然受限,你无法在自己Java程序中直接使用该类,因为它的构造函数是私有的(private)。但是我们仍然能获得它的实例,方法如下:
Unsafe unsafe;try { Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); unsafeField.setAccessible(true); unsafe = (Unsafe)unsafeField.get(null); } catch (Throwable t) { unsafe = null; }Unsafe类的更多介绍和用法可以参照http://mishadoff.github.io/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/
我们将使用Unsafe类的如下方法来实现Java中的sizeof()
//获得对象中一个非静态字段的偏移量public native long objectFieldOffset(java.lang.reflect.Field field);//获得数组对象第一个元素的偏移量public native int arrayBaseOffset(java.lang.Class aClass);//获得数组每一个元素所占内存大小public native int arrayIndexScale(java.lang.Class aClass);
sizeof()方法代码如下:
注意:不同的Java虚拟机,参数会各不一样,以下代码只适用于32位的HotSpot虚拟机。
package test;import java.lang.reflect.Array;import java.lang.reflect.Field;import java.lang.reflect.Modifier;import sun.misc.Unsafe;public class JUtil {/**对象头部的大小 */private static final int OBJECT_HEADER_SIZE = 8;/**对象占用内存的最小值*/private static final int MINIMUM_OBJECT_SIZE = 8;/**对象按多少字节的粒度进行对齐*/private static final int OBJECT_ALIGNMENT = 8;public static long sizeOf(Object obj) {//获得Unsafe实例Unsafe unsafe; try { Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); unsafeField.setAccessible(true); unsafe = (Unsafe)unsafeField.get(null); } catch (Throwable t) { unsafe = null; } //判断对象是否为数组 if (obj.getClass().isArray()) { Class<?> klazz = obj.getClass(); int base = unsafe.arrayBaseOffset(klazz); int scale = unsafe.arrayIndexScale(klazz); long size = base + (scale * Array.getLength(obj)); if ((size % OBJECT_ALIGNMENT) != 0) { size += OBJECT_ALIGNMENT - (size % OBJECT_ALIGNMENT); } return Math.max(MINIMUM_OBJECT_SIZE, size); } else { //如果数组对象则迭代遍历该对象的父类,找到最后一个非静态字段的偏移量 for (Class<?> klazz = obj.getClass(); klazz != null; klazz = klazz.getSuperclass()) { long lastFieldOffset = -1; for (Field f : klazz.getDeclaredFields()) { if (!Modifier.isStatic(f.getModifiers())) { lastFieldOffset = Math.max(lastFieldOffset, unsafe.objectFieldOffset(f)); } } if (lastFieldOffset > 0) { lastFieldOffset += 1; if ((lastFieldOffset % OBJECT_ALIGNMENT) != 0) { lastFieldOffset += OBJECT_ALIGNMENT - (lastFieldOffset % OBJECT_ALIGNMENT); } return Math.max(MINIMUM_OBJECT_SIZE, lastFieldOffset); } } //该对象没有任何属性 long size = OBJECT_HEADER_SIZE; if ((size % OBJECT_ALIGNMENT) != 0) { size += OBJECT_ALIGNMENT - (size % OBJECT_ALIGNMENT); } return Math.max(MINIMUM_OBJECT_SIZE, size); } }public static void main(String[] args) throws InterruptedException {System.out.println(JUtil.sizeOf(new MyClass()));//输出32Thread.sleep(100000);//阻塞线程,为了使用jmap工具}}下面测试所用的类:
package test;public class MyClass {private byte a;private int c;private boolean d;private long e;private Object f; }最后我们使用jmap工具来检查计算的结果是否正确
上图中的各项含义分别是:类的编号,实例的个数,占用内存的大小,类的名字。
可以看出sizeof()方法计算出来的结果是完全正确的。
0 0
- Java计算一个对象占用内存的大小
- Java计算一个对象占用内存的大小
- 计算一个对象占用的内存
- java常用对象的内存占用大小
- 如何计算java对象占用的内存
- 如何计算java对象占用的内存
- 如何计算java对象占用的内存
- 计算Java对象占用的内存
- 如何计算java对象占用的内存
- 如何计算java对象占用的内存
- 如何计算java对象占用的内存
- JAVA内存使用--如何计算一个Java对象占用的字节数
- JAVA内存使用--如何计算一个Java对象占用的字节数
- JAVA内存使用--如何计算一个Java对象占用的字节数
- 【JAVA内存】如何计算一个Java对象占用的字节数
- JAVA内存使用--如何计算一个Java对象占用的字节数
- JAVA内存使用--如何计算一个Java对象占用的字节数
- JAVA内存使用--如何计算一个Java对象占用的字节数
- uiimage 动态gif
- hadoop1.0向hadoop2.0 distcp数据
- 合格合格呵呵就看看
- C语言几个预编译指令的用法
- 破解 Windows 下Markdown 编辑器 MarkdownPad 2
- Java计算一个对象占用内存的大小
- gsoap入门学习笔记(一)---概论(专业术语以及通信过程概述)
- Java泛型学习一:泛型术语
- 面试官询问的刁钻问题
- Linux技巧
- 解决ORA-01747表列名无效
- 浙大PAT 1065. A+B and C (64bit) (20)
- hadoop2.0 执行框架
- 西途假期签证办理专家3v茵