文章目录
解释一下对象的创建过程(半初始化)DCL单例到底需不需要加volatile?(单例模式,指令重排)对象在内存中的存储布局(对象和数组的存储不同)对象头包括什么?(Markword,class pointer)对象怎么定位?(直接、间接)对象怎么分配?(栈上-线程本地-Edum-Old)Object o = new Object()在内存中占多少个字节?为什么hotspot不使用c++对象来代表java对象?Class对象是在堆还是方法区?
解释一下对象的创建过程(半初始化)
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没有。
Class对象是在堆还是方法区?
对象的创建与OOP-Klass模型