不管你有没有对象,都带你了解下对象

JVM的数据类型

基本数据类型

 

引用类型(reference)

        在JDK8,64位HotSpot上, 引用数据类型(reference)都是直接指针,如果开启了压缩指针,就是4字节,否则就是8字节

 

对象组成

一个对象包含3部分数据:对象头(Object Header)、实例数据(Instance Data)、对齐填充(Padding)

 

 

而实例对象和数组对象又有所不同

 

问题

下图是oom时自动dump的文件,通过mat打开分析,可以看到,有接近30万个对象本文不讨论如何分析oom,而是关注:为什么Shallow Heap列中每个对象是占用24字节?

 

User.java

 

 

对象内存布局分析

要使用到的三个参数

 

 

另外,还需要用到JOL工具,JOL是openjdk提供的用来验证JVM的内存布局方案的,ClassLayout.parseInstance(new User(1, "qzcsbj"));

 

-XX:+PrintFlagsFinal默认,均为开启状态

 

因为是64位(Java HotSpot(TM) 64-Bit Server VM ),所以Mark Word占8个字节UseCompressedClassPointers默认开启,所以Class Pointer占4个字节所以对象头(Object Header)占用8+4=12字节Integer和String分别占4个字节,所以实例数据(Instance Data)占用4+4=8字节为了计算机高效寻址,使用padding对齐填充为8的倍数,所以最小8的倍数值为24,所以对齐填充(Padding)占用4个字节。这里也就知道上面问题为什么是24字节了。下面继续分析。

 

-XX:+PrintFlagsFinal -XX:-UseCompressedOops -XX:-UseCompressedClassPointers

 

因为是64位(Java HotSpot(TM) 64-Bit Server VM ),所以Mark Word占8个字节UseCompressedClassPointers关闭,所以Class Pointer占8个字节所以对象头(Object Header)占用8+8=16字节Integer和String分别占8个字节,所以实例数据(Instance Data)占用8+8=16字节总共32字节,是8的倍数,所以不需要填充

 -XX:+PrintFlagsFinal -XX:+UseCompressedOops

开启UseCompressedOops,默认会开启UseCompressedClassPointers,会压缩klass pointer 这部分的大小,由8字节压缩至4字节,间接的提高内存的利用率

 

 

因为是64位(Java HotSpot(TM) 64-Bit Server VM ),所以Mark Word占8个字节UseCompressedClassPointers默认开启,所以Class Pointer占4个字节所以对象头(Object Header)占用8+4=12字节Integer和String分别占4个字节,所以实例数据(Instance Data)占用4+4=8字节为了计算机高效寻址,使用padding对齐填充为8的倍数,所以最小8的倍数值为24,所以对齐填充(Padding)占用4个字节

 

 -XX:+PrintFlagsFinal -XX:+UseCompressedOops -XX:-UseCompressedClassPointers

  

因为是64位(Java HotSpot(TM) 64-Bit Server VM ),所以Mark Word占8个字节UseCompressedClassPointers关闭,所以Class Pointer占8个字节所以对象头(Object Header)占用8+8=16字节Integer和String分别占4个字节,所以实例数据(Instance Data)占用4+4=8字节总共24字节,是8的倍数,不需要填充 

-XX:+PrintFlagsFinal -XX:+UseCompressedClassPointers

UseCompressedOops默认开启

 

 

 -XX:+PrintFlagsFinal -XX:+UseCompressedClassPointers -XX:-UseCompressedOops

虽然开启UseCompressedClassPointers,但是依然为false,因为UseCompressedClassPointers的开启是依赖于UseCompressedOops的开启

 

 

所以,开启UseCompressedOops 也默认开启UseCompressedClassPointers(可以显示指定关闭),关闭UseCompressedOops,也默认关闭UseCompressedClassPointers(不可以显示指定开启,否则报错:Java HotSpot(TM) 64-Bit Server VM warning: UseCompressedClassPointers requires UseCompressedOops)。


如果显示指定UseCompressedOops,UseCompressedClassPointers保持默认:如果关闭(-XX:-UseCompressedOops):对象头16字节(8+8,mark word和klass pointer都是占用8字节),reference占用8字节;

如果开启(-XX:+UseCompressedOops):对象头12字节(8+4,mark word占用8字节,klass pointer占用4字节),reference占用4字节。

                                                                      --- 转载 微信公证号 全栈测试笔记

posted @ 2020-12-02 13:48  Echo_梦里花落知多少  阅读(346)  评论(0编辑  收藏  举报