浅堆、深堆、对象集

注意:环境为jdk8

1.对象内存布局

        在HotSpot虚拟机里,对象在堆内存中的存储布局可以划分为三个部分:对象头(Header),实例 数据(Instance Data)和对齐填充(Padding)。

HotSpot虚拟机对象的对象头部分包括两类信息。

第一类是用于存储对象自身的运行时数据,如哈 希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,这部 分数据的长度在32位和64位的虚拟机(未开启压缩指针)中分别为32个比特和64个比特,官方称它 为“Mark Word”。对象需要存储的运行时数据很多,其实已经超出了32、64位Bitmap结构所能记录的 最大限度,但对象头里的信息是与对象自身定义的数据无关的额外存储成本,考虑到虚拟机的空间效 率,Mark Word被设计成一个有着动态定义的数据结构,以便在极小的空间内存储尽量多的数据,根 据对象的状态复用自己的存储空间。例如在32位的HotSpot虚拟机中,如对象未被同步锁锁定的状态 下,Mark Word的32个比特存储空间中的25个比特用于存储对象哈希码,4个比特用于存储对象分代年 龄,2个比特用于存储锁标志位,1个比特固定为0,在其他状态(轻量级锁定、重量级锁定、GC标 记、可偏向)下对象的存储内容。

对象头的另外一部分是类型指针,即对象指向它的类型元数据的指针,Java虚拟机通过这个指针 来确定该对象是哪个类的实例。并不是所有的虚拟机实现都必须在对象数据上保留类型指针,换句话说,查找对象的元数据信息并不一定要经过对象本身。此外,如果对 象是一个Java数组,那在对象头中还必须有一块用于记录数组长度的数据,因为虚拟机可以通过普通 Java对象的元数据信息确定Java对象的大小,但是如果数组的长度是不确定的,将无法通过元数据中的信息推断出数组的大小。

2.Shallow Heap(浅堆)

2.1解释

  • Shallow Heap是指对象本身占用的内存大小。它只考虑对象的直接内存消耗,不包括该对象引用的其他对象。
  • 例如,一个简单的Java对象包含一些基本类型的字段和对象引用,那么Shallow Heap就是这些字段的大小总和。

2.2占用字节说明

一个对象引用会占据4个字节,一个int类型会占据4个字节,long型变量会占据8个字节,每个对象头需要占用16个字节(不开启指针压缩)

2.3样例

B 的 Shallow Heap

  • address (String 引用): 4字节
  • longitude (BigDecimal 引用): 4字节
  • latitude (BigDecimal 引用): 4字节
  • 对象头: 16字节

因此,B 的 Shallow Heap 大小为:Shallow Heap of B=16+4+4+4=28字节

String的Shallow Heap

String 对象由以下部分组成:

  • 对象头: 16字节
  • int hash: 4字节
  • int offset: 4字节
  • int count: 4字节
  • char[] 引用: 4字节

因此,String 对象的 Shallow Heap 大小为:

Shallow Heap of String=16+4+4+4+4=32字节

此外,String 还引用了一个 char[] 数组。假设字符串“张三”和“北京”的长度分别为2和2,则 char[] 数组的 Shallow Heap 大小为:

  • char[] 数组对象头: 16字节
  • char[] 数组数据: 2 * 2字节 = 4字节

总的 Shallow Heap 大小为:

Shallow Heap of char[]=16+4=20字节

BigDecimal的Shallow Heap

BigDecimal 对象包含以下字段:

  • int scale: 4字节
  • int precision: 4字节
  • int bitCount: 4字节
  • int compact: 8字节(使用 long 存储)
  • BigInteger intVal 引用: 4字节
  • 对象头: 16字节

因此,BigDecimal 对象的 Shallow Heap 大小为:Shallow Heap of BigDecimal=16+4+4+4+8+4=40字节

BigDecimal 对象通常还包含一个 BigInteger 对象,假设其包含一个 int[] 数组引用。BigInteger 对象的 Shallow Heap 大小为:

  • 对象头: 16字节
  • int[] 引用: 4字节
  • signum: 4字节

假设 BigIntegerint[] 数组包含2个元素(每个 int 4字节),则 Shallow Heap 为:

Shallow Heap of BigInteger=16+4+4+(16+2∗4)=48字节

3.Retained Set(保留集)

3.1解释

  • Retained Set是指一个对象以及它所有直接或间接引用的对象的集合。如果从GC root删除这个对象,该集合中的所有对象也会被删除。
  • Retained Set中的对象都是依赖于特定对象存在的对象。

3.2样例

B 的 Retained Set 包含:B 本身,Stringaddress 字段),BigDecimallongitudelatitude 字段),BigInteger 及其相关数组。

4.Retained Heap(深堆)

  • Retained Heap是指从GC root无法到达该对象时,内存管理器可以回收的总内存大小。它包括了该对象以及所有直接或间接被其引用的对象的Shallow Heap。
  • 换句话说,如果某个对象被垃圾回收,导致所有与之相关的对象也将被垃圾回收,那么这些对象的总内存就是Retained Heap。
Java中,合的拷贝构造函数通常只提供浅拷贝,而不是深拷贝。这意味着原始合和克隆合中存储的对象是相同的,指向Java堆内存中相同的位置。如果修改了原始合中的对象信息,克隆合也会受到影响,反之亦然。所以,如果需要进行合的深拷贝,需要采用其他方法。 一个可行的深拷贝合的方法是使用递归来克隆合中的对象,直到基本数据类型或者不可变类。这个过程可以通过创建一个新的对象,并将原始合中的每个元素逐个克隆并添加到新的合中。这样就可以确保克隆合与原始合完全独立。然后就可以对克隆合进行任意的修改,而不会对原始合产生任何影响。 在给定的引用中,展示了一个使用递归方法来进行深拷贝的示例代码。该示例代码是一个求取整数数组的所有子的方法,其中使用了递归来生成子。递归的过程中,通过创建新的对象,并将原始合中的元素逐个添加到新的合中,实现了深拷贝的效果。 因此,要进行Java合的深拷贝,可以使用递归方法来克隆合中的对象,确保克隆合与原始合完全独立。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [java中list合的深度拷贝](https://blog.csdn.net/u010398493/article/details/52840076)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值