JVM-对象创建过程
一、创建过程
初始化指的是:例如a=12 ,实际上jvm初始化的时候 会先给a初始化一个0的值,后面在init方法赋值具体的数值
分配内存机制:
1.指针碰撞机制(默认机制):如果java堆的内存的空间是绝对规整的,就维护一个内存指针作为分界点,新分配对象空间就挪动指针。因为系统会存在并发的问题,这里指针碰撞解决并发问题采用的是CAS机制(失败重试),本地线程分配缓冲(Thread local allocation buffer TLAB),即每个线程在内存中独立分配一个空间,通过XX:+/UseTLAB参数来设定虚拟机是否使用TLAB(JVM会默认开启XX:+UseTLAB),XX:TLABSize 指定TLAB大小
2.空闲列表:如果堆内存空间不规则,使用的内存和空间的内存是零散存储的,就需要维护一个空闲列表,记录当前堆上面哪些空间空闲,哪些空间正在使用。在分配的时候,划分一块足够大的区域去存储
二、对象头
1.Mark word标记字段:在并发环境下,要有加锁的考虑,这些信息就是存储在Mark word里面,不同的锁状态,后面的存储不一样
2.Klass Pointer(类型指针):对象一般都是在堆中开辟内存空间存储,类型指针就是对象在堆中指向方法区类元信息的指针
3.数组长度:这个是数组对象才有的
依赖:
实例代码:
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.17</version>
</dependency>
public class JOLSample {
public static void main(String[] args) {
ClassLayout layout = ClassLayout.parseInstance(new Object());
System.out.println(layout.toPrintable());
System.out.println();
ClassLayout layout1 = ClassLayout.parseInstance(new int[]{});
System.out.println(layout1.toPrintable());
System.out.println();
ClassLayout layout2 = ClassLayout.parseInstance(new A());
System.out.println(layout2.toPrintable());
}
// ‐XX:+UseCompressedOops 默认开启的压缩所有指针
// ‐XX:+UseCompressedClassPointers 默认开启的压缩对象头里的类型指针Klass Pointer
// Oops : Ordinary Object Pointers
public static class A {
//8B mark word
//4B Klass Pointer 如果关闭压缩‐XX:‐UseCompressedClassPointers或‐XX:‐UseCompressedOops,则占用8B
int id; //4B
String name; //4B 如果关闭压缩‐XX:‐UseCompressedOops,则占用8B
byte b; //1B
Object o; //4B 如果关闭压缩‐XX:‐UseCompressedOops,则占用8B
}
}
object header: mark (mark word)
object header: class:(klass pointer)
object alignment gap:(补位空间 padding)
三、为什么要指针压缩
1.减轻GC压力,保障堆内可以存储更多的对象