Java对象在内存的存储布局

以下截图及相关信息,均来源于马士兵公开课中


对象在内存的存储布局

对象在内存的存储布局.jpg
大小: 存储信息
对象头(markword) 8 字节 hashcode 、GC年龄代、锁标识状态
类型指针(class pointer) 4 字节 指向 Class 类对象的引用
实例数据(instance data) 不确定 相关变量信息(int 4字节,long 8字节),引用类型(占用4字节)
数组长度(length,仅数组时存在该属性) 4字节 存储数组长度

锁升级过程对象信息

image.png

查看对象信息

一、引入依赖

<!-- 用于查看对象结构-->
<dependency>
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.9</version>
</dependency>

二、查看对象信息

synchronized 锁信息在对象头中

(a)测试代码

/**
 * 测试synchronized 锁信息在对象头中
 */
public static void testSynchronized(){
    Object object = new Object();

    System.out.println("========== synchronized 加锁之前 ==========");
    System.out.println(ClassLayout.parseInstance(object).toPrintable());

    synchronized (object){
        System.out.println("========== synchronized 加锁之后 ==========");
        System.out.println(ClassLayout.parseInstance(object).toPrintable());
    }

    System.out.println("========== synchronized 释放锁之后 ==========");
    System.out.println(ClassLayout.parseInstance(object).toPrintable());
}

(b)输出结果:

image.png

hashcode 值在对象头中

(a)测试代码

/**
 * 测试 hashcode值在对象头中
 */
public static void testHashcode(){
    Object object = new Object();
    System.out.println("========== 查看对象的hashcode[未调用对象的hashcode方法,的输出] ==========");
    System.out.println(ClassLayout.parseInstance(object).toPrintable());
    System.out.println("========== 查看对象的hashcode[调用对象的hashcode方法,之后的输出] ==========");
    object.hashCode();
    System.out.println(ClassLayout.parseInstance(object).toPrintable());
}

(b)测试结果

image.png

关于 new Object() 的问题:

1.请解释一下对象的创建过程?

image.png

2.请问DCL要不要加Volatile问题?

DCL(双 if 判断)代码

class SingleDemo3 {
    /**
     * volatile 防止指令重排
     */
    private static volatile SingleDemo3 singleDemo3 = null;

    private SingleDemo3() {}

    public static SingleDemo3 getSingleDemo3() {
        if (singleDemo3 == null) {
            synchronized (SingleDemo3.class) {
                if (singleDemo3 == null) {
                    singleDemo3 = new SingleDemo3();
                }
            }
        }
        return singleDemo3;
    }
}

我们发现创建对象过程中,不是原子操作,因此可能出现错误的情况。

假如指令重排:先建立了关联,后初始化,在未初始化前使用了这个对象就会存在问题

image.png

3.对象在内存中的存储布局?

对象头(markword) + 类型指针(class pointer) + 实例数据(instance data) + 数组长度(length,仅数组时存在该属性)

4.对象头具体包括什么?

synchroized锁标识状态,GC分代年龄,hashcode值(第一次调用才会生成)

5.对象怎么定位?

直接访问、句柄

6.对象怎么分配?

栈上-线程本地-Eden-Old

7.Object o = new Object() 在内存中占用多少字节?

markword(8字节) + classpointer(4字节) + 对齐(4字节) = 16字节

8.为什么hotspot 不使用 c++ 对象来代表 java 对象?

9.Class对象是存储在堆还是方法区?

方法区

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容