跳转至

JVM

class定义

对象占据空间

  • 对象头(12个字节):
  • 对象标记(Mark Word,8字节):哈希码、GC标记、锁信息等;
  • 类元信息:类元数据(KClass)的首地址;

  • 实例数据:本类对象的实例成员变量和所有可见的父类成员变量

  • 对齐填充(padding):8字节的整数倍;

规范

  • Java中创建对象和赋值是分开的,不保证执行顺序;

线程的工作内存和主内存?TODO

可见性

  • volatile 对基本类型或对象实例进行修饰,确保修改后所有线程立即可见
  • volatile 屏蔽指令重排序的语义(JDK 5后);
  • synchronizedLock 也能够保证可见性,同一时刻只有一个线程获取锁然后执行同步代码:
  • 线程解锁前,释放锁之前会将对变量的修改刷新到主存当中
  • 线程加锁时,将清空工作内存中,从而使用共享变量时需要从主内存中重新读取最新的值

happens-before 原则

happens-before 原则:Java内存模型具有一定有序性,不需要通过任何手段就能够得到保证的有序 。

  • 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作;用来保证程序在单线程中执行结果的正确性,但无法保证程序在多线程中执行的正确性。
  • 锁规则:一个unLock操作先行发生于后面对同一个锁的lock操作
  • volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作;
  • 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;
  • 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作;
  • 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生;
  • 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行;
  • 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始;

如果两个操作的执行次序无法从happens-before原则推导出来,那么它们就不能保证它们的有序性,虚拟机可以随意地对它们进行重排序。

A Happens-Before B,不是说A要发生在B之前,而是说如果在时间顺序上A发生在B之前,那么A中的操作对B中的操作可见

lock前缀

观察加入volatile关键字和没有加入volatile关键字时所生成的汇编代码发现,加入volatile关键字时,会多出一个lock前缀指令,实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:

1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;

2)它会强制将对缓存的修改操作立即写入主存;

3)如果是写操作,它会导致其他CPU中对应的缓存行无效。

实现

HotSpot

OpenJ9