共计 2214 个字符,预计需要花费 6 分钟才能阅读完成。
JVM 系列笔记目录
- 虚拟机的根底概念
- class 文件构造
- class 文件加载过程
- jvm 内存模型
- JVM 罕用指令
- GC 与调优
硬件层数据一致性
– 存储器层次结构
从 L6-L0 空间由大变小,速度由慢到快。
- 缓存一致性算法
CPU 实现缓存一致性的协定很多,其中 intel 应用的 MESI(Modified Exclusive Shared Or Invalid) 协定。具体能够参考:[MESI–CPU 缓存一致性协定](https://www.cnblogs.com/z0037…
古代 CPU 的数据一致性实现 = 缓存锁 (MESI…) + 总线锁
- 缓存行
缓存读取时的单位,个别是 64Byte
应用缓存行的对齐可能提高效率
- 伪共享
位于同一缓存行的 2 个不同的数据,被 2 个不同的 CPU 锁定,产生相互影响的伪共享问题。
如何解决?应用缓存行的对齐可能提高效率
CPU 乱序问题
– 概念
CPU 为了进步执行效率,会在一条指令执行的过程中 (比方去内存取数据 ( 慢 100 倍)),去同时执行另一条指令,前提是两条指令没有依赖关系。具体参考:[古代 cpu 的合并写技术对程序的影响](https://www.cnblogs.com/liush…
- 合并写
CPU 上有一个 WriteCombinBuffer,仅 4 个字节,比 L1 等级还高,某些写操作会合并在一起提交。[古代 cpu 的合并写技术对程序的影响](https://www.cnblogs.com/liush…
- 乱序证实
CPU 乱序景象有大佬写程序模仿进去了,具体参考:Memory Reordering Caught in the Act
如何保障在特定状况下保障不乱序
硬件级别
X86 CPU 级别内存屏障
sfence store fence 在 sfence 指令前的写操作必须在 sfence 指令后的写操作前实现 lfence load fence 在 lfence 指令前的读操作必须在 lfence 指令后的读操作前实现 mfence mixed fence 在 mfence 指令前的读写操作必须在 mfence 指令后的读写操作前实现
CPU 原子指令
如 x86 上的”lock …”指令是一个 Full Barrier,执行时会锁住内存子系统来确保执行程序,甚至跨多个 CPU
总结:Software Locks 通常应用了内存屏障或原子指令来实现变量可见性和放弃程序程序
JVM 级别
JSR113 标准规定了 4 种内存屏障
LoadLoad 屏障 对于语句 Load1;LoadLoad;Load2,在 Load2 及后续读取指令要读取的数据被拜访前,保障 Load1 要读取的数据被读取结束 StoreStore 屏障 对于语句 Store1;StoreStore;Store2, 在 Store2 及后续写操作执行前,保障 Store1 的写入操作对其它处理器可见 LoadStore 屏障 对于语句 Load1;StoreStore;Store2, 在 Store2 及后续写操作被刷出前,保障 Load1 要读取的数据被读取结束 StoreLoad 屏障 对于语句 Store1;StoreStore;Load2, 在 Load2 及后续读取指令要执行前,保障 Store1 的写入操作对其它处理器可见
sychronized/volatile 在字节码、JVM、硬件 OS 层面实现细节
– sychronized
- 字节码层面
sychronized m() : AccessFlag : ACC_VOLATILE
sychronized(this){} : monitorenter monitorexit monitorenter
- JVM 层面
C/C++ 调用操作系统的同步操作
- 硬件 OS 层面
X86 : lock cmpxchg / xxx
-volatile
- 字节码层面
AccessFlag : ACC_VOLATILE- JVM 层面
volatile 内存区域都加屏障
StoreStoreBarrier volatile 写操作 StoreLoadBarrier
LoadLoadBarrier volatile 读操作 LoadStoreBarrier
- 硬件 OS 层面
windows lock 指令实现 或是 MESI 实现
面试 new Object() 6 连问
-
1. 解释对象的创立过程
该问题联合上篇博客:JVM 系列【3】Class 文件加载过程不难答复进去。
class loading
class linking (vertification prepraration resolution)
class initiazing
new 申请内存空间
成员变量赋初始值
调用构造方法 <init>: 成员变量赋初始值;执行构造方法语句,super() 父类结构。
- 2. 对象在内存中的存储布局
对象在内存中布局分一般对象和数组对象。
一般对象 4 局部:对象头 markword(8 字节)、ClassPointer 指针 (4 或 8 字节)、实例数据、padding 对齐为 8 的倍数。
数组对象 5 局部,和一般对象相似,但两头是数组长度 4 字节和具体的数组数据。
- 3. 对象头具体包含什么
对象头 markword(8 字节) 具体内容和对象锁状态有关系,其中最高位 2 位是锁状态中,最低 3 位用作锁标记位,两头 4 位是 GC 年龄,如下。
- 4. 对象怎么定位
通过句柄池和间接指针,具体参考:拜访对象两种形式 – 句柄和间接指针
- 5. 对象怎么调配?
对象的调配其实和垃圾回收 GC 有关系,后续总结 GC 具体讲。
- 6.Object o = new Object() 在内存中的占用多少个字节
16 个字节,依据第 2 点的内存布局能够算出。
常识分享,转载请注明出处。学无先后,达者为先!