通过dump分析Java对象在内存中到底占用多大空间?

一、内存结构分析
1、概念:
Shallow Size:Shallow size就是对象本身占用内存的大小,不包含其引用的对象。
retained size: 自身对象+引用对象的retained大小。
2、jvm内存创建对象组成部分
1)对象头包括两部分:
第一部分markword,用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等
第二部分类型指针,虚拟机通过这个指针来确定这个对象是哪个类的实例
2)实例数据
实例数据部分是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容。无论是从父类继承下来的,还是在子类中定义的,都需要记录起来。
3)填充数据
最后一块对齐填充空间并不是必然存在的,也没有特别的含义,它仅仅起着占位符的作用。这是由于HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍,换句话说,就是对象的大小必须是8字节的整数倍。
3、对象头占用空间
1. 在32位系统下,存放Class引用指针的空间大小是4字节,MarkWord是4字节,对象头为8字节。
2. 在64位系统下,存放Class引用指针的空间大小是8字节,MarkWord是8字节,对象头为16字节。
3. 在64位开启指针压缩的情况下 -XX:+UseCompressedOops,存放Class引用的空间大小是4字节,MarkWord是8字节,对象头为12字节。
4. 如果对象是数组,需要另外增加4字节,用来记录数组长度,也就是一个int类型的对象,占4字节
二、确认机器环境情况:
查看机器位数
java -d64 -version

 

查看是否开启压缩
jinfo -flag UseCompressedOops 462238
目前机器JVM内存情况
 
三、对象占用内存分析及优化实战
1、dump内存文件是使用JProfiler分析
2、内存具体情况分析
1)int[]数组占用内存空间分析:
 对象头12byte+2*4数据+ 4(记录数组长度) = 24byte
 
2)字符串分析:
单纯一个String: 的shallowSize 24byte= 对象头(8+4)byte+4byte(字段属性hash)+8byte(long序列号号) 
单纯一个char[] 内存大小shallowSize  16 btype = 对象头(8+4)byte+4byte(数组长度)
一个String最小占用内存:40Byte
一个String占用内存大小Retained = (shallowSize 24byte) +( char[] 的shallowSize  16 btype) +一个char 2byte*N个字符 = 40 +2N + (40 +2N)/8,然后补齐到8的倍数(40 +2N)/8。其中N是字符个数
如规则adowner = 40+2*10 + (40+2*10)/8 = 64
 
 
3)Long占用内存分析
Long 24  = 12Byte(对象头)+8btype + 4byte(对齐补充) 
 
3、优化点
1)时间字符串优化成 int,占用内存效果:64byte->4byte  降低原来 1/16
2)hashMap的key由String 优化成Long,内存占用优化效果:72byte->24byte  降低原来 1/3
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章