寄存器中的内存最小速度最快,硬盘容量最大,速度最小,cup的第三级缓存是共享内存。 java
对于一个在同一行的数据XY,会被同时加载进CPU,这个现象叫cache line缓存行对齐,缓存行对齐具体内容能够看看这篇文章若是左边的CPU核心加载了X并进行修改,可是此时并无将数据写回进主内存,或者是第三级缓存,此时右边的CPU核心将X读进,并修改,此时就会产生数据不一致的状况。对于左边修改了数据右边如何才能知道,这是硬件层级须要解决的。 多线程一致性的硬件支持有一下集中方式。数组
锁总线的方式。总线锁会锁住bus总线,使得其余CPU不能访问内存中的其余地址,于是效率极低。CPU的共享内存都是经过 缓存
MESI(英特尔CPU) 等等之类的缓存一致性协议,相对于总线锁的方式MESI的性能好不少。bash
在特定状况下CPU会进行指令重排,以保证高效的执行。CPU如何保证特定的状况下不不乱序执行。经过内存屏障来保证指令的有序性。多线程
下面是三种CPU指令内存屏障指令。jvm
sfence:在sfence指令前的写操做必须在sfence后写操做完成以前完成操做。即在两次写操做之间加个屏障使其不能被重排。性能
lfence:在lfence指令前的读操做必须在lfence后的读操做完成以前完成操做。即在两次读操做之间加个屏障使其不能被重排。spa
mfence:在mfence指令前的读写操做必须在mfence的读写操做完成以前完成操做。即在一次读一次写和另外一次读和一次写之间加一个屏障使其不能被重排。线程
CPU保证有序执行除了可使用mfence,还可使用3d
jvm内存屏障,对上面的CPU内存屏障进行组合,有以下四种屏障
jvms 2.4 2.5
PC 程序计数器 Program Counter
Each Java Virtual Machine thread has its own pc (program counter) register.
每一个Java虚拟机线程都有本身的程序计数器的存储空间。
At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method for that thread.
在任什么时候候,每一个Java虚拟机线程都在执行单个方法的代码,即该线程的当前方法。
If that method is not native , the pc register contains the address of the Java Virtual Machine instruction currently being executed.
若是该方法不是本机方法,则pc寄存器包含当前正在执行的Java虚拟机指令的地址。
存放指令位置
虚拟机的运行,相似于这样的循环:
while( not end ) {
取PC中的位置,找到对应位置的指令;
执行该指令;
PC ++;
}
复制代码
JVM Stack
Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread.
每一个Java虚拟机线程都有一个私有Java虚拟机堆栈,与该线程同时建立。
A Java Virtual Machine stack stores frames
每一个Java虚拟机存储的都是栈帧
Heap
The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads.
java 虚拟机有个全部线程共享的堆内存。
The heap is the run-time data area from which memory for all class instances and arrays is allocated.
堆是运行时数据区,从中分配全部类实例和数组的内存。
Method Area
The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads.
Java虚拟机具备一个在全部Java虚拟机线程之间共享的方法区域。
It stores per-class structures
存储每一个类的结构
Runtime Constant Pool
A run-time constant pool is a per-class or per-interface run-time representation of the constant_ pool table ina class file
Native Method Stack
An implementation of the Java Virtual Machine may use conventional stacks called native method stacks
Direct Memory
JVM能够直接访问的内核空间的内存 (OS 管理的内存)
NIO , 提升效率,实现zero copy
上面的内容总结起来就是下面这张图
每一个线程都有本身的栈内存,里面存放的是栈帧,若是有调用native方法就还存在native method stack,还有本身program counter程序计数器,用来记录每条指令的执行,当CPU切换线程的时候方便知道以前线程执行到哪条指令,全部线程共享堆内存和方法区,方法区有两种实现,在jdk8以前方法区叫PermGen永久代,jdk8及其之后的版本都叫Meta Space 元数据区。
栈帧:A frame is used to store data and partial results, as well as to perform dynamic linking, return values for methods, and dispatch exceptions.
栈帧是用来存储数据部分结果,和执行动态连接,返回方法的值和处理异常调度。
![]()
咱们看一下一个简单的方法的执行过程的栈帧是怎么样的。
pubilc class Test1{
pubilc static void main(String [] args){
Test h = new Test();
h.m1();
}
}
pubilc class Test{
public void m1(){
int i = 200;
}
}
复制代码
编译后的Test1字节码为:
0 new #2 <com/yhx/Test>
3 dup
4 invokespcial #3<com/yhx/Test<init>>
7 istore_1
8 iload_1
9 invokespcial #3<com/yhx/Test<m1>>
12 return
复制代码
对应Test字节码为:
0 ipush 200
3 istore_1
4 return
复制代码
咱们看上面指令,在这条 invokespcial #3<com/yhx/Test>也就是初始化以前执行了一个dup指令,也就是上面初始化对象的是哪一个流程执行完第二个流程,此时这个对象的成员变量的值若是是引用型的则仍是为null,这个dup指令是将main方法栈帧中Operand Stacks的(如上图)h复制一份,而后出栈,init操做拿着出栈后的值进行初始化操做,这个时候栈内的对象引用就变为初始化以后的了。 接下来就是“istore_1”变量1就是h,将初始化好的内存引用赋值给h,而后“iload_1”把变量1加载进本地变量表。