JVM运行时数据区简介

JVM简图

一、程序计数器

1.1 定义

  程序计数器是一个记录着当前线程所执行的字节码的行号指示器,它记的是下一条JVM指令的执行地址。它是Java对硬件的抽象,在物理上是由寄存器实现的。

1.2 作用

  在说明程序计数器的作用之前,先来看看这段简单的Java代码。

public class PrintNum {
    public static void main(String[] args) {
        System.out.println(1);
        System.out.println(2);
        System.out.println(3);
    }
}

  下面是该源代码被编译成JVM指令的结果。
)
  观察这张图,不难发现每个指令前都有一个数字,这是指令的偏移地址,简称为行号,程序计数器的作用就是存储下一条指令的行号。
  以上图为例,当第一条指令执行时,JVM会将下一条指令的行号“3”放入程序计数器中。当第一条指令执行完时,解释器会根据程序计数器中的行号拿到下一条指令,继续运行。

  为什么要多此一举先把下一条指令的行号放入程序计数器中,直接取指令然后执行不是更简单吗?
  。JVM是支持多个线程同时运行的,这就涉及到CPU的调度问题了。线程甲正执行的好好的, 大哥CPU告诉甲说,你累了,我陪会儿乙,甲只好乖乖休息。一段时间后,大哥回来了,这时甲就可以根据程序计数器中的行号取到下一条指令接着执行。
  这里有一点要注意,因为程序计数器记录的是行号,是会重复的,所以多个线程不能同时用一个,不然就乱了。所以程序计数器是线程私有的。

1.3 特点

  • 线程私有。
  • 不会存在内存溢出。程序计数器中的行号永远只会有一个,当前指令执行时,会拿下一条指令的行号替换当前的行号。因此就不存在内存溢出问题。

二、虚拟机栈

2.1 定义

  :虚拟机栈是每个线程运行所需要的内存。
  栈帧:每个栈由多个栈帧组成,对应着每次方法调用时所占用的内存。
在这里插入图片描述

2.2 作用

  虚拟机栈是用于描述Java方法执行的内存模型。每一个方法执行时,会创建一个栈帧,栈帧的结构为:局部变量表、操作数栈、动态链接、方法出口,可以理解成一种数据结构,专门用于描述Java方法执行的数据结构。虚拟机栈的最小单位就是栈帧。
  线程运行中,当执行到一个方法时,就会生成一个栈帧并压入栈中。当这个方法执行完之后,会将这个栈帧弹出,释放对应的内存空间。
  一个栈中可能同时存在多个栈帧,如方法一调用方法二时,就会将两个栈帧都压入栈中。
​   注意每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法。

简单理解:如当执行main方法时,就会开启一个main线程。这时虚拟机就要拿出一块区域给这个线程使用,这一块区域就是虚拟机栈。同时也不难理解,虚拟机栈也和程序计数器是线程私有的。
  Java的线程的运行其实就是在执行一个个方法,JVM通过栈帧来表示方法的执行。于是当线程中有方法执行时,就需要对应生成一个栈帧放入虚拟机栈中。表示此线程有此方法正在运行。当该方法执行完之后,这个栈帧也会弹栈,释放其内存,所以也不涉及垃圾回收。

2.3 特点

  • 不涉及垃圾回收。因为当方法执行完,栈帧会弹栈,对应的内存就会释放掉。不会产生垃圾。
  • 注意栈的大小,当分配给栈的内存过大时,相应地,同时可运行地线程数就会减少。

三、本地方法栈

3.1定义

本地方法Java语言是有限制的,不能直接和操作系统打交道,因此就需要通过调用CC++编写的方法来和底层交互。这些用CC++编写地方法就是本地方法。(代码中用native修饰的方法就是本地方法。)
本地方法栈:本地方法执行用到的内存空间就是本地方法栈。

四、堆

4.1 定义

  堆是运行时数据区中最重要的区域,也是垃圾回收的重点关注对象。由于现代垃圾收集器大部分都是基于分代收集理论设计的,在这种理论下,堆的结构被分为新生代,老年代,其中新生代又被分为伊甸园和幸存区,如下图。
在这里插入图片描述
  当在程序中new一个对象时,JVM会首先将其放到伊甸园区。如果伊甸园区即将占满,没有空间给下一个对象时,就会进行一个MinorGC,此时会回收新生代中已死的对象。并将存活对象放入幸存区From中。这些存活对象由于经历过一次GC,所以它们的寿命为1。之后如果伊甸园区又满了,就会再进行MinorGC,此时会将伊甸园中和幸存区From中的对象放入幸存区To中,并将这些对象的寿命加1,之后交换From区和To区。
  一个对象经过15GC(这个数值不是固定的,最大为15)后依旧存活,会将其放入老年代。当老年代和新生代的空间都被占满时,会进行一次FullGC,对整个堆空间进行一次垃圾回收。
  如果想要了解堆的垃圾回收,可以参考这篇博文。链接: JVM垃圾回收机制

4.2 特点

  • 存在内存溢出。如果新建的对象一直被回收就会造成内存溢出问题。
  • 是线程共享的。所以堆中对象都要考虑线程安全问题。

五、方法区

5.1 定义

  方法区是JVM所有线程共享的区域,它存储了与类结构相关的信息:运行时常量池,成员变量,方法数据,成员方法、构造方法的代码。它的大小就决定了系统可以保存多少种类。
  方法区在虚拟机启动时创建,它在逻辑上是堆的组成部分(具体实现上是否为堆的一部分视厂商而定,如永久代,元空间都是其实现)。JVM规范并不强制方法区的位置。

5.2 具体实现

  在1.6中方法区的实现叫永久代,1.8叫元空间。在1.8中,方法区被移出JVM内存,被放置在本地内存(操作系统内存)中。
JVM1.6 方法区
JVM1.8 方法区
  从这两张图中可以看出有一个特别的区域——字符串常量池StringTable,它在1.7之后被放进了堆中。如果想要了解这块区域,可以看看这篇文章,链接: 字符串常量池StringTable简介

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值