java内存对齐_《深入理解java虚拟机》读书笔记:Java对象的内存布局

本文详细解析了Java对象在HotSpot虚拟机中的内存布局,包括对象头、实例数据及内存对齐等内容。揭示了Integer与Byte封装类型的内存占用差异,并讨论了内存对齐的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个int类型4占4个字节的内存,一个byte一个字节。但是他们的封装类型Integer,Byte对象内存损耗还是一样的吗?并不是,而且差距十分大。

HotSpot虚拟机中,一个普通的Java对象由3部分构成

对象头

类内定义的实例数据

内存对齐

15c01125b7047bad33859cb5b1c39613.png

2不必多说,Java对象不存定义好的实例字段存啥。

对象头又分两部分,Mark Word和类型指针。Mark Word存储对象运行时数据,如对象的hashcode,对象的分代年龄,锁状态等等。对象的分代年龄完全是为了JVM的Young GC设计的,每经历一次Young GC且存活下来的新生代对象,对象的分代年龄变会加一。直到这个字段增长到阈值,这个对象便会晋升到老年代(tenured generation)。这个字段给的是4个bit,也就是说一个java对象最多经历16次Young GC并且没被回收,那么它将进入老年代。hashcode占25bit,锁标志位占2bit,一个bit固定为0.也就是说整个Mark Word占4个字节。

每种对象实例在方法区都会与一个Class对象与之相对应。对象头的类型指针便是用来定位它的类的元数据。为何要存这个数据?原因之一便是,方法区也要GC(确切的说是Full GC),如果没有一个类实例指向方法区的Class对象,那么这个Class对象便会被卸载回收。不知道大家有没有经历过java.lang.OutOfMemoryError: PermGen space 这样的错误。如果类一直在加载,永久代必然会被打爆。32位的JDK,类类型指针占4个字节。

现在说说内存对齐。内存对齐可不是jvm的专利,C/C ++ 下,类对象也是会内存对齐的。HotSpot要求对象的起止地址必须是8的倍数,由于对象头正好8个字节,因此当类字段没对齐时,就需要通过填充来对齐。为何要对齐呢?数据不是占内存越小越好吗?这个时候就得提提我们的cpu高速缓存了(L1 cache, L2 cache),这些缓存都是64字节一行。

最后来回答开头的问题,Integer大小是int的4倍(用了额外的4Byte补齐),Byte是byte的16倍(用了额外的7Byte补齐)。你算出来了吗?

fe7bc357c1f5499cd7f6b5481fba254b.png

两年前看《effective java》,有一个章节提到尽量用8大原生类型,那个时候对java对象内存布局完全没概念。现在回想起来,这个suggesstion是很有建设意义的。能节约很多堆内存啊,尤其是在从DB读取大量字段的时候。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值