天天看点

JVM调优前置知识-深堆Retained Heap和浅堆Shallow Heap

学习 尚硅谷 宋红康 JVM从入门到精通 的学习笔记

深堆Retained Heap和浅堆Shallow Heap

浅堆的大小不会超过深堆,顶多是平等

浅堆算是对应Java的浅拷贝, 深堆算是对应Java的深拷贝

浅堆的意思

浅堆(Shallow Heap)是指一个对象所消耗的内存,在32位系统中,一个对象的引用会占据4个字节,一个int类型会占据4个字节,long类型变量会占据8个字节,每个对象头需要占用8个字节,反射堆快照格式的不同,对象的大小可能会向8字节进行对齐(总大小肯定能够被8除尽,除不尽就补齐就可以了.),

以String为例子:2个int值总共占用8个字节,对象引用占用了4个字节,对象头占用了8个字节,合计总共20个字节,向8字节对齐,所以占用24字节(jdk7中)

JVM调优前置知识-深堆Retained Heap和浅堆Shallow Heap

这24字节为String对象的浅堆大小.它与String的value实际取值无关,无论字符串长度如何,浅堆大小始终是24字节.

value是引用类型,不论存什么值,value是"hello"也好,是"helloworld"也罢,浅堆大小都是24个字节.

对象头代表根据类创建的对象的对象头,还有对象的大小不是可能向8字节对齐,而是就向8字节对齐

浅堆是一个对象消耗的内存的大小,不包括它对其它引用的对象的大小的计算,比如说

比如说下面的student对象,我实例化一个 new Student(3,“张三”); 这个对象, 那么3 这个int基本类型就是会计算在浅堆里面,String和 List是引用变量会指向新的堆空间里面的实体,我们就不记录那个堆对象的实体的大小了,引用导向记录也要占用4个字节,那么也要记录下这占用的四个字节.

JVM调优前置知识-深堆Retained Heap和浅堆Shallow Heap

深堆的意思

是shallow heap的总和,能刻画出对象如果被回收,相关的数据都能被回收的大小,这个就是深堆

保留集(Retained Set)

对象A的保留集指当前对象A被垃圾回收后,可以被释放的所有的对象集合(包括对象A本身),即对象A的保留集可以被认为是只能通过对象A被直接或者间接访问到的所有对象的集合.通俗的来说就是仅仅被对象A所持有的对象的集合.

例子: 比如说字符串是s1的value值是"hello'", 字符串s2的value值也是"hello",那么这两个value值共用的是一个地址值.      

假如说我没有s2这个字符串了, 我只有s1字符串, "hello"这个值只是被s1字符串引用,那么计算s1的保留级的使用也应该给这个 “hello” 字符串的大小也记录在内. 因为"hello"字符串只能是被s1这个字符串所访问.

但是如果有s2这个字符串,s2也持有"hello"的引用,那么在回收s1字符串变量的时候不能回收"hello"这个字符串,因为"hello"字符串被s2也引用了,那么s1的保留级就没有"hello"这个字符串了.

总结: 能够被回收的数据(没被其它引用的)才能称为保留级的.

深堆(Retained Heap):

深堆是指对象的保留集中所有的对象的浅堆大小的总和.

注意:浅堆指的是对象本身占用的内存大小,不包括其内部引用对象的大小.一个对象的深堆指只能通过这个对象访问到的(直接或间接)所有对象的浅堆之和,即对象被回收之后,可以释放的真实空间.

注意:

当前深堆大小 = 当前对象的浅堆大小 + 对象中所包含对象的深堆大小

对象的实际大小

对象的实际大小定义为一个对象所能触及的所有对象的浅堆大小的和,也就是通常意义上我们说的对象的大小,与深堆相比,这个对象大小的日常开发中更为直观和被人接受,但是实际上,这个概念和垃圾回收无关