最近在学习java对象内存布局方面的一些知识,主要是想知道一个java对象到底占 用多少内存空间,以及java对象在内存中究竟是什么样子的。c/c++中的sizeof运算符可以方便地告诉咱们一个变量占用的内存空间,可是在 java中却没有直接提供这种机制。若是想获取java对象占用的内存大小,能够利用java的Instrumentation机制。 java.lang.instrument.Instrumentation这个接口提供了getObjectSize(Object objectToSize),可以告诉咱们一个对象的大小。如何获取Instrumentation对象,网上有不少资料,这里再也不赘述。 html
- public static void main(String[] args)
- {
- // 经过pre-agent获取Instrumentation对象
- Instrumentation instr = AgentGetter.getInstrumentation();
-
- System.out.println(instr.getObjectSize(new Object()));
- }
Java对象的内存布局:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。不管是32位仍是64位的HotSpot,使用的都是8字节对齐。
也就是说每一个java对象,占用的字节数都是8的整数倍。(对象头 + 实例数据 + padding) % 8等于0且0 <= padding < 8。在网上看到各类介绍如何手动计算对象大小的文章,总结了几点:
1.基本数据类型占用的字节数,JVM规范中有明确的规定,不管是在32位仍是64位的虚拟机,占用的内存大小是相同的。
2.reference类型在32位JVM下占用4个字节,可是在64位下可能占用4个字节或8个字节,这取决因而否启用了64位JVM的指针压缩参数UseCompressedOops。
3.new Object()这个对象在32位JVM上占8个字节,在64位JVM上占16个字节。
4.开启(-XX:+UseCompressedOops)指针压缩,对象头占12字节; 关闭(-XX:-UseCompressedOops)指针压缩,对象头占16字节。
5.64位JVM上,数组对象的对象头占用24个字节,启用压缩以后占用16个字节。之因此比普通对象占用内存可能是由于须要额外的空间存储数组的长度。
6.对象内存布局中的实例数据,不包括类的static字段的大小,由于static字段是属于类的,被该类的全部对象共享。
java
关于对象内存布局的计算规则,能够参考这篇文章讲的很详细"Java对象内存结构"。 c++
更具体的能够参考“一个Java对象到底占用多大内存?”这篇文章。在网上搜索的过程当中看到了java object layout这个小工具,可以打印出类的布局信息。 bootstrap
项目的主页是:http://openjdk.java.net/projects/code-tools/jol/, 数组
项目代码在http://central.maven.org/maven2/org/openjdk/jol/。 安全
下载jol-core-0.3.2.jar以后,将其加入项目的build path,经过下面的代码就能够查看某个类的布局信息。 maven
- package jol;
-
- import org.openjdk.jol.info.ClassLayout;
- import org.openjdk.jol.util.VMSupport;
-
-
-
- public class T1 {
-
- public static void main(String[] args) throws Exception {
-
- System.out.println(VMSupport.vmDetails());
-
- System.out.println(ClassLayout.parseClass(VO.class).toPrintable());
- }
-
- }
运行这段代码,能够看到jol输出以下信息:
- Running 64-bit HotSpot VM.
- Objects are 8 bytes aligned.
- Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
- Array element sizes: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
-
- jol.VO object internals:
- OFFSET SIZE TYPE DESCRIPTION VALUE
- 0 16 (object header) N/A
- 16 8 long VO.b N/A
- 24 4 int VO.a N/A
- 28 4 (loss due to the next object alignment)
- Instance size: 32 bytes (estimated, the sample instance is not available)
- Space losses: 0 bytes internal + 4 bytes external = 4 bytes total
能够看到jol工具,可以显示出对象头的大小,以及每一个实例字段的偏移,进而计算对象占用的内存大小。
jol工具还提供了一个命令行工具jol-cli-0.3.2-full.jar,包含了main方法可以直接在命令行运行,查看类的布局信息。能够从这里下载jol-cli工具。
- #查看jdk系统类的布局信息
- >java -jar jol-cli-0.3.2-full.jar internals java.lang.Object
- #若是咱们本身的jar放在C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\下,那么会自动加载;
- #若是咱们本身的jar放在C:\Program Files\Java\jdk1.7.0_80\jre\lib\下,那么不会自动加载(多是由于安全问题#,bootstrap类加载器仅仅加载jdk的核心类);
- >java -jar jol-cli-0.3.2-full.jar internals net.aty.VO
- #方式1:指定classpath,查看本身的类布局
- >java -jar jol-cli-0.3.2-full.jar internals -cp mydemo.jar net.aty.VO
- #方式2:指定classpath,查看本身的类布局
- >java -cp mydemo.jar;jol-cli-0.3.2-full.jar org.openjdk.jol.Main internals net.aty.VO
上面几种方式都可以正确运行,可是下面这种方式是错误的,会报错ClassNotFoundException。
- #注意:这种方式会报错:java.lang.ClassNotFoundException:
- #这是由于:若是采用了-jar参数来运行可执行的jar包,JVM会忽略你设置的classpath以及全部环境变量
- java -cp mydemo.jar -jar jol-cli-0.3.2-full.jar internals net.aty.VO
http://blog.csdn.net/aitangyong/article/details/46416667 工具