JVM系列【4】内存模型

JVM系列笔记目录

  • 虚拟机的基础概念
  • class文件结构
  • class文件加载过程
  • jvm内存模型
  • JVM经常使用指令
  • GC与调优

硬件层数据一致性

- 存储器层次结构

file

从L6-L0 空间由大变小,速度由慢到快。html

-缓存一致性算法

CPU实现缓存一致性的协议不少,其中intel 使用的MESI(Modified Exclusive Shared Or Invalid)协议。具体能够参考:[MESI--CPU缓存一致性协议](https://www.cnblogs.com/z0037...面试

file

现代CPU的数据一致性实现=缓存锁(MESI...) +总线锁算法

-缓存行

缓存读取时的单位,通常是64Byte
使用缓存行的对齐可以提升效率windows

-伪共享

位于同一缓存行的2个不一样的数据,被2个不一样的CPU锁定,产生互相影响的伪共享问题。数组

如何解决? 使用缓存行的对齐可以提升效率缓存

CPU乱序问题

- 概念

CPU为了提升执行效率,会在一条指令执行的过程当中(好比去内存取数据(慢100倍)),去同时执行另外一条指令,前提是两条指令没有依赖关系。具体参考:[现代cpu的合并写技术对程序的影响](https://www.cnblogs.com/liush...jvm

-合并写

CPU上有一个WriteCombinBuffer,仅4个字节,比L1等级还高,某些写操做会合并在一块儿提交。[现代cpu的合并写技术对程序的影响](https://www.cnblogs.com/liush...布局

-乱序证实

CPU乱序现象有大佬写程序模拟出来了,具体参考: Memory Reordering Caught in the Actthis

如何保证在特定状况下保证不乱序

硬件级别

X86 CPU级别内存屏障spa

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字节和具体的数组数据。

    file

  • 3.对象头具体包括什么

    对象头markword(8字节)具体内容和对象锁状态有关系,其中最高位2位是锁状态中,最低3位用做锁标志位,中间4位是GC年龄,以下。

    file

  • 4.对象怎么定位

    经过句柄池和直接指针,具体参考:访问对象两种方式--句柄和直接指针

  • 5.对象怎么分配?

    对象的分配其实和垃圾回收GC有关系,后续总结GC详细讲。

    file

  • 6.Object o = new Object() 在内存中的占用多少个字节

    16个字节,根据第2点的内存布局能够算出。

知识分享,转载请注明出处。学无前后,达者为先!
相关文章
相关标签/搜索