一、内存结构分析


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




java 如何dump内存泄露 java dump 内存_数组长度


 


查看是否开启压缩


jinfo -flag UseCompressedOops 462238



java 如何dump内存泄露 java dump 内存_数组长度_02


目前机器JVM内存情况



java 如何dump内存泄露 java dump 内存_java 如何dump内存泄露_03


 


三、对象占用内存分析及优化实战


1、dump内存文件是使用JProfiler分析



java 如何dump内存泄露 java dump 内存_字符串_04


2、内存具体情况分析


1)int[]数组占用内存空间分析:


 对象头12byte+2*4数据+ 4(记录数组长度) = 24byte



java 如何dump内存泄露 java dump 内存_数组长度_05


 


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


 



java 如何dump内存泄露 java dump 内存_数据_06



java 如何dump内存泄露 java dump 内存_字符串_07


 


3)Long占用内存分析


Long 24  = 12Byte(对象头)+8btype + 4byte(对齐补充) 



java 如何dump内存泄露 java dump 内存_数据_08


 


3、优化点


1)时间字符串优化成 int,占用内存效果:64byte->4byte  降低原来 1/16



java 如何dump内存泄露 java dump 内存_数据_09


2)hashMap的key由 String 优化成Long,内存占用优化效果:72byte->24byte  降低原来 1/3



java 如何dump内存泄露 java dump 内存_java 如何dump内存泄露_10