以下截图及相关信息,均来源于马士兵公开课中
对象在内存的存储布局
大小: | 存储信息 | |
---|---|---|
对象头(markword) | 8 字节 | hashcode 、GC年龄代、锁标识状态 |
类型指针(class pointer) | 4 字节 | 指向 Class 类对象的引用 |
实例数据(instance data) | 不确定 | 相关变量信息(int 4字节,long 8字节),引用类型(占用4字节) |
数组长度(length,仅数组时存在该属性) | 4字节 | 存储数组长度 |
锁升级过程对象信息
查看对象信息
一、引入依赖
<!-- 用于查看对象结构-->
<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)输出结果:
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)测试结果
关于 new Object() 的问题:
1.请解释一下对象的创建过程?
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;
}
}
我们发现创建对象过程中,不是原子操作,因此可能出现错误的情况。
假如指令重排:先建立了关联,后初始化,在未初始化前使用了这个对象就会存在问题
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对象是存储在堆还是方法区?
方法区