java对象的对齐规则

本文探讨了Java对象在JVM堆内存中的内存布局,包括对象头、实例数据域和对齐填充。通过openjdk jol工具和sun.misc.Unsafe展示了对象内存布局的查看方法。文章介绍了Java对象的内存布局由对象头(包括mark word和元数据指针)、实例数据域和可能的对齐填充组成,并详细讨论了Java的对齐规则,包括对象内对齐和对象间对齐。此外,还提及了C/C++中的对齐规则,并解释了为何Java要坚持8byte对齐。
摘要由CSDN通过智能技术生成

零、注记

本文是一次讨论的流水账,旨在讲明原理就行了,行文大家不要抱太大的希望。

另外,特别重要的是,本文是基于hotspot来讨论的,不同的java虚拟机可能是有不同的,这一点,一定要注意。

 

一、什么是对象的内存布局

简单一句话:对象实例在jvm堆内存中存放的结构。就是随便实例化一个对象new Object(),他在堆内存里面是怎么放置的。

看下面这个jol工具给出的java.math.BigInteger内存布局的例子:一个对象的内存布局包含了对象头object header、实例数据域和对齐填充alignment padding(可能有,可能没有,下面再细说)。

***** 64-bit VM, compressed references enabled: ***************************
java.math.BigInteger object internals:
 OFFSET  SIZE  TYPE DESCRIPTION                    VALUE
      0    12       (object header)                N/A
     12     4   int BigInteger.signum              N/A
     16     4 int[] BigInteger.mag                 N/A
     20     4   int BigInteger.bitCount            N/A
     24     4   int BigInteger.bitLength           N/A
     28     4   int BigInteger.lowestSetBit        N/A
     32     4   int BigInteger.firstNonzeroIntNum  N/A
     36     4       (loss due to the next object alignment)
Instance size: 40 bytes (estimated, the sample instance is not available)
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

 

二、查看对象内存布局的工具

1. openjdk jol

openjdk官网给了一个查看对象内存布局的工具,jol(java object layout)http://openjdk.java.net/projects/code-tools/jol/

怎么拿呢?openjdk给了maven的依赖:

Use as Library Dependency
OpenJDK Community semi-regularly pushes the releases to Maven Central. Therefore, you can use it right away by setting up the Maven dependency:
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>put-the-version-here</version>
</dependency>
It is a good idea to review JOL Samples and CLI tools source before using the tool at its full capacity as the library.

怎么用呢?上面给的jol的链接页面,最下面官方给了jol samples的链接,使用极其简单,就是一个ClassLayout就没了。示例就懒得给了,看samples吧。

jol sampleshttp://hg.openjdk.java.net/code-tools/jol/file/tip/jol-samples/src/main/java/org/openjdk/jol/samples/

jol sourcecodehttp://central.maven.org/maven2/org/openjdk/jol/

如果不想看samples呢?这篇参考文章给了用例和讲解《JDK之JVM中Java对象的头部占多少byte》https://my.oschina.net/u/2518341/blog/1838006

那如果不想用jol工具怎么办呢?卧槽,我好难啊。。。

2. sun.misc.Unsafe

  • sun.misc.Unsafe.objectFieldOffset方法获取第一个field的偏移地址(弊端:当对象头后面有padding的时候,你看不出来,什么时候有padding呢,下面会细说)
  • JDK8及之前,是用的sun.misc.Unsafe
  • JDK9有两个Unsafe,除了sun.misc.Unsafe还提供了jdk.internal.misc.Unsafe,但是jdk.internal.misc.Unsafe不像sun.misc.Unsafe是可以通过反射使用的,实际上目前在JDK9以后的版本中,sun.misc.Unsafe中组合了jdk.internal.misc.Unsafe的实例,实际上sun.misc.Unsafe是一个简单包装,你可以自己翻翻源码。

至少有两种方式可以获取到sun.misc.Unsafe实例对象:

  • 通过反射sun.misc.Unsafe的构造函数获取其实例对象;
  • 通过反射sun.misc.Unsafe的实例属性theUnsafe获取其实例对象;
package cn.wxy.unsafe;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import sun.misc.Unsafe;

public class UnsafeUtils {
	/**
	 * 通过反射sun.misc.Unsafe的构造函数获取其实例对象
	 * 
	 * @return sun.misc.Unsafe
	 */
	public static Unsafe getUnsafeByConstructor() {
		Constructor<Unsafe> constructor = null;
		try {
			constructor = Unsafe.class.getDeclaredConstructor();
			const
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值