JVM运行时数据区Runtime Data Area

135 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

1. 简介

image.png

运行时数据区可分为6块地方,其中直接内存方法区是线程共享的,JVM栈本地方法栈程序计数器是线程独有的。

2 程序计数器 Program Counter

是存放下一条指令地址的地方
虚拟机运行的时候会取PC中的位置,找到对应的指令,然后执行该指令,再PC++,然后再取PC中的位置,依次循环直到结束。

3 本地方法栈 native method stacks

jave调用JNI,调用C和C++写的方法的时候使用的栈

4 直接内存 Direct Memory

NIO,提高效率,实现0拷贝
这些内存不归JVM管,归操作系统管
以前当网络上传过来数据的时候,以前是先存放到内核空间的内存里,JVM访问这个数据的时候是先拷贝到自己的内存然后访问,这就有一个拷贝的过程,效率比较低。
现在是增加了NIO,使用直接内存。直接可以访问内核空间上网络传过来的内容。提高了效率。

5 方法区 method area

放各种各样的已经被加载的class,以及常量池的内容,静态变量,即时编译器编译后的代码

6 堆 Heap

堆用来存放对象实例
内部分为新生代老年代
新生代又分为eden区和两个survivor幸存者区
eden和两个survivor的大小比例位8:1:1
一个对象new出来之后,会先尝试栈上分配,也就是往栈上存储,当栈上存储不下时,放入Eden区,当Eden区满了之后,进行MinorGC也叫YGC,然后将存活对象放入一个survivor区,当Eden区下一次进行YGC的时候,将存活对象与之前那个survivor区的存活对象一同存入另一个survivor,就这样来回拷贝,当分代年龄超过设定值时,则存入老年代。或者需要拷贝的对象占用超过survivor的一半时,将年龄最大的存入老年代。

6.1 如何找到垃圾

  • reference count 引用计数
  • Root Searching 根可达算法

6.2 GC常用垃圾清除算法

标记清除

  • 执行过程:找到没用的对象,清除出来
  • 优点:算法相对简单,存活对象比较多的情况下效率较高
  • 缺点:扫描两遍,效率偏低,容易产生碎片

拷贝

  • 执行过程:将内存一分为二,将一半内存活的对象拷贝到另一半内存,连续存放
  • 优点:适用于存活较少的情况,只扫描一次,效率提高,没有碎片
  • 缺点:空间浪费,移动复制对象需要调整对象引用

标记压缩

  • 执行过程:将存活对象整理到内存的连续区域
  • 优点:不会产生碎片,方便对象分配,不会产生内存减半
  • 缺点:扫描两次,需要移动对象,效率偏低 在年轻代使用的是拷贝,老年代使用标记清除或者标记压缩

7 JVM栈

栈里边是一个一个的栈帧,对应一个一个的方法

7.1 栈帧

一个栈帧包含四个部分

  1. Local Variable Table 局部变量表,存储局部变量
  2. Operand Stack 操作数栈
  3. Dynamic Linking 动态链接,指到运行时常量池的符号链接,若是没有解析就进行动态解析,若是已经解析则直接拿过来用
  4. return address a() -> b(),若是方法a调用了方法b, b方法的返回值放在什么地方以及返回a方法时该从哪条指令继续

7.2 针对栈帧的一个分析

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

当使用i = i++;时,运行原理为

  1. 将8压入栈帧自己的操作数栈
  2. 将栈顶数据8出栈,放到局部变量表
  3. 将局部变量表的数据8拿出来压栈
  4. 将局部变量表的数据8加1变为9
  5. 将栈顶的8赋值给局部变量表i,此时9又变为8
  6. 所以此时返回8

当使用i = ++i;时,运行原理为

  1. 将8压入栈帧自己的操作数栈
  2. 将栈顶数据8出栈,放到局部变量表
  3. 将局部变量表的数据8加1变为9
  4. 将局部变量表的数据9拿出来压栈
  5. 将栈顶的9赋值给局部变量表i
  6. 所以此时返回9 所以当我们平时所说的,i++是先取值再加,就是先将i放入操作数栈,然后对局部变量表的i进行加1. ++i先加再取值是先将局部变量表的i进行加1,然后放入操作数栈。但是给i赋值的时候,是将操作数栈的值赋给局部变量表的i值。输出的时候是输出局部变量表的i值。