JVM之Runtime Data Area和JVM Instructions分析
结构图
包含哪些组件以及作用
一个java文件在javac指令后编译成class文件会经过 load、link、initializing后进入到runtime data area
runtime data area包含很多的组件,他们分别是:
- heap(堆)
- JVM stacks (JVM栈):每一个线程都有自己的JVM stack,而JVM stack里面又可以包含很多的frame(栈帧),每个frame都对应一个方法。
- frame(栈帧):由 Local Variables(局部变量表)+ Operand Stacks(操作数栈)+ dynamic linking(动态链接)+ return address(返回地址) 组成
- native method stacks(本地方法栈):一些C++编译的native方法在运行性的时候会用到native method stacks
- Program Counter(PC 程序计数器):计数器,每个线程都有自己的计数器,线程切换的时候,用来记录代码执行的位置。
- method area(方法区):用于存储类结构。是所有线程共享的。JDK1.8之前叫做PremSpace,字符串存储在这里,FGC时不会清理。1.8之后叫MetaSpace,字符串存储于heap,FGC时会清理。
- Direct Memory(直接内存):OS操作系统直接管理的内存,BIO要访问外界传递过来的资源,需要从直接内存中copy一份资源到JVM内存进行操作。NIO可以直接访问直接内存。
局部变量表
例子1
public class TestIPulsPlus {
public static void main(String[] args) {
int i = 8;
//i = i++;
i = ++i;
System.out.println(i);
}
}
输出结果为9,先看一下本地变量表
再看一下字节码指令是如何实现的
如果把++i,该成i++,输出结果为8,再来看一下字节码指令执行
例子2
public void m1() {
int i = 200;
}
局部变量表
它的局部变量表有两个,分别为下标值为0的变量this,下标值为1的变量i
例子3
public void add(int a, int b) {
int c = a + b;
}
本地变量表:
add方法的局部变量表有四个,下标值为0的this,下标值为1的a,下标值为2的b,下标值为3的c
例子4
public class Hello_03 {
public static void main(String[] args) {
Hello_03 h = new Hello_03();
int i = h.m1();
}
public int m1() {
return 100;
}
}
本地变量表就不看了,注意一点的是非static方法LocalVariableTable下标值为0的变量一定是this。
main方法指令:
再扩展几个invokeXXX指令:
- InvokeStatic:调用静态方法时,会触发这个指令
- InvokeVirtual:普通方法调用,自带多态特性
- InvokeInterface:接口方法调用
- InovkeSpecial :可以直接定位,不需要多态的方法 private 方法 , 构造方法
- InvokeDynamic:lambda表达式或者反射或者其他动态语言scala kotlin,或者CGLib ASM,动态产生的class,会用到的指令
戏入人生
有理解不到位或者不清晰的地方,请留言指正,谢谢。