文章目录
解释一下对象的创建过程(半初始化)
-
Object o = new Object();
- new Object()先在内存中申请空间,创建出对象,半初始化;
- o在main方法栈帧中产生,存放堆中对象的内存地址;
- 最后指针指向堆对象,建立关联。
详细参考:图解JAVA对象的创建过程
DCL单例到底需不需要加volatile?(单例模式,指令重排)
- DCL:double check lock双重检测锁;
- 用volatile修饰的对象,会禁止对该对象存储位置操作的指令重排。
- 通过问题一我们知道对象创建分为三个步骤,这三个步骤之间有可能会发生指令重排。多线程条件下,一个线程操作对象:执行完半初始化,下一步可能会先建立连接再执行对象的init方法,另一个线程可能会在对象建立完连接便提取对象,此时对象处于半初始化状态。
- volatile:禁止指令重排,会避免使用到半初始化状态的对象。
对象在内存中的存储布局(对象和数组的存储不同)
对象头包括什么?(Markword,class pointer)
- markword:hashcode、gc、锁信息(读hotspot源码)(8个字节)
- class pointer 指向类对象(开启压缩4个字节,不压缩8个字节)
对象怎么定位?(直接、间接)
-
hotsopot的具体实现,实现方式是直接指针。
-
句柄(间接)方式:方便gc操作,GC需要经常移动对象。
对象怎么分配?(栈上-线程本地-Edum-Old)
- jvm读到new关键字,首先会尝试在栈上分配对象(经过逃逸分析和标量替换),栈上创建对象的好处:栈内对象出栈之后,生命周期结束,不需要GC介入。。
- TLAB:thread local allcation buffer 线程本地分配缓冲区,管理线程的分配竞争。
Object o = new Object()在内存中占多少个字节?
=右边:
-
class pointer: 指向类对象(开启压缩4个字节,不压缩8个字节)
-
markword:hashcode、gc、锁信息(读hotspot源码)(8个字节)
-
instance data:按数据量变化,没有则为0字节
-
最后对齐(被8整除)
=左边:
- o也占用空间,压缩4个字节,不压缩8个字节。
为什么hotspot不使用c++对象来代表java对象?
- vritual pointer虚函数表的指针在c++有,在java没有。