如你所知,Java是一门面向对象的编程语言。咱们日常在写代码的时候也是在不停的操做各类对象,那么当你在写出User user = new User();
这样一行代码的时候,JVM都作了些什么呢?程序员
在Hotspot虚拟机中一个对象的内存布局分为三个部分:对象头、实例数据、对齐填充。编程
对象头又有两部分的信息,第一部分是用于存储对象自身的运行数据(HashCode、GC分代年龄、锁状态标志等)。另外一部分是类型指针,指向它的类元数据,虚拟机经过这个指针肯定这个对象是哪一个类的实例(若是使用句柄池方式则不会有)。若是是数组还会有一个记录数组长度的以下表所示:数组
内容 | 说明 |
---|---|
Mark Word | 对象的hashCode或锁信息等 |
Class Metadata Address | 对象类型数据指针 |
Array length | 数组长度 |
Mark Word是一个非固定的数据结构以便在极小的空间内存储尽可能多的信息,它会根据对象的状态复用本身的存储空间。各状态下的存储内容以下表所示:微信
标志位 | 状态 | 存储内容 |
---|---|---|
01 | 未锁定 | 对象HashCode、分代年龄 |
00 | 轻量级锁定 | 指向锁记录的指针 |
10 | 重量级锁定 | 指向锁记录的指针 |
11 | GC标记 | 空 |
01 | 可偏向 | 偏向线程ID、偏向时间戳、对象分代年龄 |
实例数据部分是真正存储的有效信息,就是在代码中定义的各类类型的字段内容。不管是父类继承下来的,仍是在子类中的。数据结构
对齐填充不是必须存在的,仅仅起着占位符的做用,由于HotSpot虚拟机要求对象的起始地址必须是8字节的整数倍。多线程
Java程序中咱们操做一个对象是经过指向这个对象的引用。咱们都知道对象存在堆中,这个引用存在虚拟机栈中。那么引用经过什么方式去定位堆中对象的位置呢?并发
上面介绍了对象的基本信息,如今来说一讲建立对象的流程: 编程语言
分配内存有两种方式:布局
没法找到足够的内存时会触发一次GC学习
分配内存时并发问题解决方案:
A a = new A();
new一个对象的简单分解动做:
其中二、3两步间会发生指令重排序,致使多线程时若是在初始化以前访问对象则会出现问题,单例模式的双重检测锁模式正是会存在这个问题。可使用volatile来禁止指令重排序解决问题;
若是有技术问题交流欢迎加我我的微信进群,你们一块儿学习😄
二维码失效添加微信号:JK1048195848