JVM内存结构—— 程序计数器,虚拟机栈 解析

1. 程序计数器(PC Register )寄存器

1.1 全称:Program Counter Register

1.2 作用

首先,java源代码 被 编译成 二进制的 字节码 (jvm指令) jvm跨平台就是这一套指令,linux 下,windows下指令都是一致的

指令 经过 解释器 把每一条指令 解释成 机器码,然后交给CPU执行,CPU只识别机器码

程序计数器作用就是: 在指令的执行过程中,记住下一条指令的执行地址

例如下面这一段字节码

在这里插入图片描述

假设代码现在执行到 地址为 7 的 这一行,指令 通过解释器 被解释成机器码被CPU 执行过程中程序计数器 会将下一条指令地址 8 进行记录

在这里插入图片描述
当指令地址为 7 的指令执行完后,解释器从 程序计数器获取下一条指令的执行地址,解释成机器码去给CPU执行,同时,在这个过程中程序计数器 会将下一条指令地址 11 进行记录,重复这个过程,直到程序结束

在这里插入图片描述

程序计数器在物理上是通过寄存器实现的,寄存器是CPU读取速度最快的

1.3 特点

  1. 线程私有的,每一个线程都有自己的程序计数器

解释说明:

java支持多线程,多个线程运行时, CPU 中调度器组件对****每一个线程进行时间片的分配

时间片内代码没有执行完,就会将线程1的状态切换为暂存,

随后切换到线程2 ,去执行线程2的代码,同理,线程2的时间片使用完,就会回到线程1 执行未完成的代码

在这里插入图片描述

  1. 不会存在内存溢出的区域(堆,栈、方法区都会出现内存溢出)

2.虚拟机栈

2.1 栈的数据结构

栈数据结构 特点 图解:

在这里插入图片描述

特点:先进后出 (类似弹夹)

2.2 java中的虚拟机栈

2.2.1 定义

全称: Java Virtual Machine Stacks (java 虚拟机栈)

  • 线程运行时的内存空间,一个线程运行需要一个栈,多个线程运行则需要多个虚拟机栈
  • 虚拟机栈组成: 一个虚拟机栈多个栈帧(Frame)组成
  • 每个线程只能有一个活动栈帧(对应着当前正在执行的方法)

栈帧:每个方法运行时内存空间(方法内的方法参数,局部变量,返回地址等等都需要内存空间)

一个栈内一个栈帧

在这里插入图片描述
一个栈内多个栈帧

在这里插入图片描述

2.2.2 栈的演示

栈的演示

2.2.3 面试注意项

1. 垃圾回收不涉及栈内存

原因;栈内存是由一个个栈帧内存组成,栈帧内存在 每一次的方法调用结束后,会弹出栈,自动进行回收,不需要垃圾回收机制管理栈内存

2. 栈内存的分配并不是越大越好

官方说明文档 地址 :

https://docs.oracle.com/en/java/javase/11/tools/java.html#GUID-7F6FB589-CB59-4B94-BE01-02F48C400243

在这里插入图片描述

官方文档中栈的默认大小Linux、macOS、Oracle 系统上都是1024KB

windows 上则是根据windows的虚拟内存来决定

解释说明:
栈内存划分越大,会影响线程数目,因为物理内存的大小是固定的
假设有100M,每一个线程需要的栈内存为1M,那么就可以有100个线程进行运作,
如果栈内存设置为4M,这样只能有25个线程进行运作
所以栈内存大小设置并非越大越好,应进行合理的设置,一般采用官方设定的默认大小就可以了

2.2.4 栈内存溢出

原因:

1. 栈帧过多导致栈帧溢出
在这里插入图片描述
一个方法的调用产生一个栈帧,会造成栈内存溢出的情况就是:递归操作,不停的反复调用

代码演示:

首先 通过 IDEA 先设置 栈的内存大小

在这里插入图片描述
在这里插入图片描述

 private  static  int count;

    public static void main(String[] args) {
        try {
            methodA();
        }catch (Throwable e) {
            e.printStackTrace();
            System.out.println(count);
        }

    }

    private static void methodA() {
        count++;
        methodA();
    }

在这里插入图片描述

java.lang.StackOverflowError 异常:栈内存溢出

在这里插入图片描述

2 栈帧过大导致栈帧溢出

一个栈帧的大小直接超出栈内存的大小,这种情况不太容易会出现。,一个 1M的栈,一个int类型的局部变量才占4个字节,要很多很多局部变量才能占满整个栈,因此这种情况不常见。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值