JMM
JMM是一套多线程读写共享数据时,对数据的可见性,有序性和原子性的原则;为什么会有内存模型这个概念?因为不同JVM版本实现不同会造成“翻译”的效果不同,不同CPU平台的机器指令有千差万别,无法保证同一份代码并发下的效果一致。所以需要一套统一的规范来约束JVM的翻译过程,保证并发效果一致性。
JMM的实现是在Unsafe类中
public final class Unsafe {
/**
* Fetches a reference value from a given Java variable, with volatile
* load semantics. Otherwise identical to {@link #getObject(Object, long)}
*/
// 从主内存中加载变量到工作内存中
public native Object getObjectVolatile(Object o, long offset);
/**
* Stores a reference value into a given Java variable, with
* volatile store semantics. Otherwise identical to {@link #putObject(Object, long, Object)}
*/
// 实现save原语
public native void putObjectVolatile(Object o, long offset, Object x);
}
操作数栈
存放操作数的栈,虚拟机把操作数栈作为其工作区域,大多数指令都要从这里弹出数据,执行运算,然后将结果压会栈中。
例如下面代码:
int a = 1;
int b = 2;
int c = a+b;
1
2
3
对应字节码指令:
0 iconst_1 // 将int 1压入操作数栈
1 istore_1 // 将操作数栈顶int类型保存到局部变量表1
2 iconst_2 // 将int 2压入操作数栈
3 istore_2 // 将操作数栈顶int类型保存到局部变量表2
4 iload_1 // 将局部变量表1的int类型压入操作数栈
5 iload_2 // 将局部变量表2的int类型压入操作数栈
6 iadd // 将操作数栈顶两int类型相加,将结果压入栈
7 istore_3 // 将操作数栈顶int类型保存到局部变量表3
动态链接
该方法对应的jvm对象在方法区的内存地址。
返回地址
保存上层方法的局部变量表及操作数栈指针,保存方法调用入口的下一条指令即上层方法的程序计数器。
附加信息
保存java虚拟机实现的一些附加信息,例如堆程序调式提供支持的信息。
很多原子操作都是建立在以上操作的基础上实现的:
/**
* Atomically exchanges the given value with the current value of
* a field or array element within the given object <code>o</code>
* at the given <code>offset</code>.
*
* @param o object/array to update the field/element in
* @param offset field/element offset
* @param newValue new value
* @return the previous value
* @since 1.8
*/
public final int getAndSetInt(Object o, long offset, int newValue) {
int v;
do {
v = getIntVolatile(o, offset);
} while (!compareAndSwapInt(o, offset, v, newValue));
return v;