zoukankan      html  css  js  c++  java
  • 内存结构篇:程序计数器

    参考:https://www.cnblogs.com/newAndHui/p/11878504.html

    一、定义

    Program Counter Register 程序计数器(寄存器)(线程独享):程序计数器是一块 较小 的内存空间,它可以看做是当前线程所执行的字节码的 行号指示器 ;在虚拟机的概念模型里(仅仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现),字节码解释器工作时,就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳准、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成 ;

    • 作用:记录正在执行的虚拟机字节码指令的地址(如果正在执行的是本地方法则为空
    • 特点:
      • 是线程私有的
      • 不会存在内存溢出
      • 生命周期随着线程,线程启动而产生,线程结束而消亡

    二、特点详解

    理解:程序计数器,可以看做是当前线程执行的字节码的 行号指示器

    //当java 文件被翻译为字节码的时候,字节码大概类似于下面的样子
    public void test() {
        0 xxxx ..
        2 xxxx ..
        4 xxxx ..
        5 xxxx ..
    }
    

    上面左边的0、2、4、5,就是类似于字节码的行号(实际是指令的偏移地址),程序计数器中保存的值就是它们;字节码解释器,就是根据它们来执行程序的。

    三、深入了解

    java是支持多线程的,当CPU执行权从 A 线程,转移到 B 线程的时候,JVM就要暂时挂起线程 A ,去执行线程 B ;当线程 A 再次得到CPU执行权的时候,又会挂起B线程,继续执行 A 线程 ;

    1、CPU是怎么记住之前的A线程,执行到哪一处的:

    CPU根本就不会记住之前执行到哪里了,它只是埋头苦干;

    2、那是什么保证了切换线程的程序可以正常执行的:

    程序计数器 ;程序计数器里面保存的是 当前线程执行的字节码的行号(看着像行号,其实是指令地址);

    3、那么,我们需要几个程序计数器呢:每个线程都需要有一个独立的程序计数器

    如果只有一个的话,切换B线程以后,程序计数器里面保存的就是B线程所执行的字节码的行号了,再切换回A线程,就蒙圈了,不知道执行到哪里了,因为,程序计数器里面保存的是B线程当前执行的字节码地址 ;因此,我们可以想象出,要为每个线程都分配一个程序计数器因此,程序计数器的内存空间是线程私有的 ;这样即使线程 A 被挂起,但是线程 A 里面的程序计数器,记住了A线程当前执行到的字节码的指令地址了 ,等再次切回到A线程的时候,看一下程序计数器,就知道之前执行到哪里了

    4、那么程序计数器,什么时候分配内存呢:

    一个线程在执行的任何期间,都会失去CPU执行权,因此,我们要从一个线程被创建开始执行,就要无时无刻的记录着该线程当前执行到哪里了!因此,线程计数器,必须是线程被创建开始执行的时候,就要一同被创建

    5、程序计数器为什么不会存在内存溢出:

    程序技术器保存的是当前执行的字节码的偏移地址,当执行到下一条指令的时候,改变的只是程序计数器中保存的地址,并不需要申请新的内存来保存新的指令地址,因此,永远都不可能内存溢出;因此,jvm虚拟机规范,也就没有规定,也是唯一一个没有规定 OutOfMemoryError 异常 的区域(即在同一块内存上更改字节码的偏移地址,不需要再创建新的内存来保存

    6、为什么当线程执行的是本地方法的时候,程序计数器中保存的值是空:

    因为本地方法是 C++/C 写的,由系统调用,根本不会产生字节码文件,因此,程序计数器也就不会做任何记录

  • 相关阅读:
    MYSQL学习中
    正则相关记录
    JS前台相关
    .net 时间格式
    SQL问题整理
    IIS 错误
    小型文件系统(littlefs)
    三极管NPN和PNP开关电路
    事件EVENT与waitforsingleobject的使用
    UpdateData(TRUE)与UpdateData(FALSE)的使用
  • 原文地址:https://www.cnblogs.com/flypig666/p/13975079.html
Copyright © 2011-2022 走看看