java 对象内存大小计算(基于64位操作系统)

        计算对象大小需要了解java对象内存布局。在HotSpot 虚拟机中,对象在内存中布局分为三块区域,对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。

对象头

        对象头主要包括Mark Word,对象指针,数组长度

Mark Word    

java 对象内存大小计算(基于64位操作系统)

        Mark Word占用8字节空间,其主要用于锁升级。

        无锁:Mark Word保存对象HashCode,锁标志位是01,是否偏向锁为0。

        偏向锁:请求进来先检查是否包括线程id,没有的话保存线程id,修改是否偏向锁标识。如果包括线程id,则判断线程id是否是本线程id,是的话继续向下执行,不是的则进行抢锁操作,抢锁成功更改线程id,失败则升级为轻量级锁。

        轻量级锁:偏向锁抢夺失败后升级为轻量级锁,jvm通过cas操作在当前线程的线程栈中开辟一块单独的空间保存指向对象锁Mark Word的指针,并且在对象锁Mark Word中保存指向这片空间的指针,如果保存成功,则表示当前线程抢到锁,继续执行。保存失败则表示抢锁失败。

        轻量级锁抢锁失败jvm使用自旋锁不断重试抢锁避免线程阻塞,当达到一定次数后(jdk1.7后jvm控制自旋次数),升级为重量级锁。

       -XX:-UseSpinning  控制是否开启自旋锁,默认开启

        重量级锁: 自旋锁自旋一定次数还没获得锁则升级为重量级锁,此时只有获取到锁的线程能执行,其余线程阻塞。

对象指针

        指向对象元数据指针,虚拟机通过指针确定对象。

        开启指针压缩:-XX:+UseCompressedOops,开启后占用4字节,默认开启。

        关闭指针压缩:-XX:-UseCompressedOops ,关闭后占用8字节。

数组长度

        数组对象额外占用4字节。

实例数据

        实例数据指对象内定义各种类型的字段。

数据类型 占用空间
boolean 1字节
byte 1字节
short 2字节
char 2字节
int 4字节
float 4字节
double 8字节
long 8字节

对齐填充

        占位作用,HotSpot VM的自动内存管理系统要求对象起始地址必须是8字节的整数倍。

对象大小计算

        空对象大小计算:Mark Word 8字节 +开启指针压缩4字节=12字节,由于需要对齐填充,则空对象为16字节。

        对象中包含一个int类型字段:Mark Word 8字节 +开启指针压缩4字节+int 4字节=16字节,此时正好为8的倍数,不需要对齐填充。

程序计算对象大小

        lucene提供计算对象大小方法

		<!-- 引入lucene -->
        <dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-core</artifactId>
			<version>4.0.0</version>
		</dependency>

  public static void main(String[] args) {

    //新建测试对象
    TestObjectSize testObjectSize = new TestObjectSize();
    // 计算指定对象及其引用树上的所有对象的综合大小
    System.out.println(RamUsageEstimator.sizeOf(testObjectSize));
    // 计算指定对象本身在堆空间的大小
    System.out.println(RamUsageEstimator.shallowSizeOf(testObjectSize));
    // 计算指定对象及其引用树上的所有对象的综合大小
    System.out.println(RamUsageEstimator.humanSizeOf(testObjectSize));
}

        

上一篇:设计模式 - 命令模式&中介者模式&组合模式~AppDelegate 解耦


下一篇:涨姿势啦!Java程序员装X必备词汇之对象标记Mark Word!