JVM学习笔记 - 03运行时数据区

356 阅读2分钟

PC程序计数器

每一个线程都要有一个pc,用于存放指令位置,虚拟机的运行,类似于这样的循环:

while(方法未执行结束) {
 ​	取PC中的位置,找到对应位置的指令;
 ​	执行该指令;
 ​	PC ++;
}

JVM Stack虚拟机栈

每一个线程对应一个栈,每个方法对应一个栈帧Frame

  • Local Variable Table 局部变量表:存放局部变量信息,局部变量表示方法内部使用到的变量,除了通常理解的局部变量之外,还包括方法参数和非static方法的this;
  • Operand Stack 操作数栈:存放中间数据
  • Dynamic Linking 动态链接:指向运行时常量池的符号链接,方法名是啥,方法类型是啥,没解析就动态解析,已经解析就直接使用。
  • return address:表示方法返回地址,即a() -> b()中。b方法返回值存放地址。

一个无聊的例子:

    public static void main(String[] args) {
        int i = 8;
        i = i++;
//        i = ++i;
        System.out.println(i);
    }

此时局部变量表中存储的是:

下标局部变量
0args
1i

i = i++的情况下反编译代码如下:

0 bipush 8     // 8压栈
2 istore_1     // 弹出栈顶值(8)给局部变量表下标为1的位置(i)
3 iload_1      // 局部变量表下标为1(i)的值压栈
6 iinc 1 by 1  // 局部变量表为1(i)的值+1 即8+1
7 istore_1     // 栈顶的值(8)再赋值回局部变量表为1的位置(i) 即最终为8
8 return

i = ++i的情况反编译代码如下:

0 bipush 8     
2 istore_1     
3 iinc 1 by 1
6 iload_1
7 istore_1
8 return

// TODO 更复杂的方法解析

Heap堆

可以看下这篇文章juejin.cn/post/687267…

Method Area方法区

用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

  1. Perm Space (jdk < 1.8) 永久区:
  • 字符串常量位于PermSpace
  • FGC不会清理
  • 大小启动的时候指定,不能变
  1. Meta Space (jdk >= 1.8) 元空间:
  • 字符串常量位于堆
  • 会触发FGC清理
  • 不设定的话,最大就是物理内存

Native Method Stack本地方法栈

  1. 本地方法可以通过JNI(Java Native Interface)来访问虚拟机运行时的数据区
  2. 存放C C++方法等

Direct Memory 直接内存

JVM可以直接访问的内核空间的内存(OS管理的内存),用于NIO,实现零拷贝。