PC 程序计数器
存放指令位置
虚拟机的运行,类似于这样的循环:
while( not end ) {
取PC中的位置,找到对应位置的指令;
执行该指令;
PC ++;
}
JVM Stack
Local Variable Table
Operand Stack
对于long的处理(store and load),多数虚拟机的实现都是原子的
jls 17.7,没必要加volatile
Dynamic Linking
https://blog.csdn.net/qq_41813060/article/details/88379473
jvms 2.6.3
return address
a() -> b(),方法a调用了方法b, b方法的返回值放在什么地方
Heap
所有线程共享同一个堆空间。
堆空间是用来存放所有类实例和数组空间分配的运行时数据区。
Method Area 所有线程共享同一个方法区,方法区用来存放 per-class structors
Runtime Constant Pool
Native Method Stack
Direct Memory 直接内存,JVM可以直接访问内核空间的内存(OS管理的内存),零拷贝(不需要拷贝),NIO用到了,提高效率
JVM可以直接访问的内核空间的内存 (OS 管理的内存)
NIO , 提高效率,实现zero copy
思考:
如何证明1.7字符串常量位于Perm,而1.8位于Heap?
提示:结合GC, 一直创建字符串常量,观察堆,和Metaspace
理解局部变量表
理解操作数栈
理解一些常用的指令
package com.mashibing.jvm.c4_RuntimeDataAreaAndInstructionSet; public class TestIPulsPlus { public static void main(String[] args) { int i = 8; //i = i++; i = ++i; System.out.println(i); } }
基于寄存器的指令集
基于栈的指令集
Hotspot中的Local Variable Table = JVM中的寄存器
DCL 单例为什么要加 volitile?因为你看下面的第一条指令,我们知道,刚new出来对象是半初始化的对象,只是赋一个默认值,而involespecial才是调用构造方法,给变量赋初始值,而这两条指令之间是可能会发生指令重排的。
store
load
pop
mul
sub
invoke
package com.mashibing.jvm.c4_RuntimeDataAreaAndInstructionSet; public class T05_InvokeDynamic { public static void main(String[] args) { I i = C::n; I i2 = C::n; I i3 = C::n; I i4 = () -> { C.n(); }; System.out.println(i.getClass()); System.out.println(i2.getClass()); System.out.println(i3.getClass()); //for(;;) {I j = C::n;} //MethodArea <1.8 Perm Space (FGC不回收) } @FunctionalInterface public interface I { void m(); } public static class C { static void n() { System.out.println("hello"); } } }