JAVA一个对象占用多少字节

通过代码计算对象的大小

先说结论:默认16个字节

工具JOL :Java Object Layout  java对象布局

引入POM文件

        <dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.10</version>
        </dependency>
public class HelloJol {
    public static void main(String[] args) {
        Object o = new Object();
        String s = ClassLayout.parseInstance(o).toPrintable();
        System.out.println(s);
    }
}

打印结果

前两行就是markWord 固定8个字节

分析java对象的组成

普通对象

对象头:markword 8  (锁信息:标识对象的状态,GC信息:对象被回收了多少次 分代年龄)

ClassPointer指针:-XX:+UseCompressedClassPointers 为4字节(默认开启) 不开启为8字节 (对象属于哪个Class)

实例数据 引用类型:-XX:+UseCompressedOops 为4字节(默认开启) 不开启为8字节 Oops Ordinary Object Pointers(成员变量的引用 比如下面的Object o)

此处的Object o = new Object()没有成员变量,实列数据占0字节  

Padding对齐,8的倍数 (64位的机器 按块来读,一下子读16个字节)

所以Object o = new Object()占用字节如下

16个字节=对象头8+ClassPoint指针 4+实列数据0+padding对其4 = 16个字节

数组对象

对象头:markword 8

ClassPointer指针同上

数组长度:4字节

数组数据:

padding对齐 8的倍数

用例测试

public class T03_SizeOfAnObject {
    public static void main(String[] args) {
        System.out.println(ObjectSizeAgent.sizeOf(new Object()));
        System.out.println(ObjectSizeAgent.sizeOf(new int[] {}));
        System.out.println(ObjectSizeAgent.sizeOf(new P()));
    }

    //一个Object占多少个字节
    // -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
    // Oops = ordinary object pointers
    private static class P {
                        //8 _markword
                        //4 _class pointer
        int id;         //4
        String name;    //4
        int age;        //4
byte b1;        //1
        byte b2;        //1

        Object o;       //4
        byte b3;        //1

    }
}

打印结果:

16 = 对象头8个 + ClassPointer指针 4个 +padding对齐 4个

16 = 对象头8个 + ClassPointer指针 4个 +数组长度 4个 +padding对齐0个

32 = 对象头8个 + ClassPointer指针 4个 + int id 4个 + name的引用四个 + int age 4个+1+1+4+1 + padding对齐

对象头具体包括什么

8个字节64位 看对象的状态分配64位。普通状态和锁定状态每一位完全不一样

主要包括

锁的标识位:标识对象的状态,

GC标记:对象被回收了多少次 分代年龄

参考JVM层面 Synchronized的实现

当一个对象已经计算过identity hash code它就无法进入偏向锁状态

对象是怎么定位的

T t = new T()

t是怎么找到堆内存中的T对象

1.间接方式 句柄池:t指向了一个结构体也就是句柄池(图中如评论所说,画错了)

这个结构体有两个指针,分别指向T对象和T.class。好处是 对象挪动t位置不变,垃圾回收效率高

2.直接指针(HotSpot的实现):T对象里面除了包括自己的成员变量之外还包括了类型指针。好处是快 一下子定位。

 

posted @ 2020-05-02 00:06  palapala  阅读(3328)  评论(6编辑  收藏  举报