什么是程序计数器?

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

———–摘抄自  周志明版  《深入理解java虚拟机》 P39

简单的理解为,是程序计数器保证了程序的正常执行 ;

有什么特点

线程私有的
是java虚拟机规范里面, 唯一 一个 没有规定任何 OutOfMemoryError 情况的区域
生命周期随着线程,线程启动而产生,线程结束而消亡

为什么具有这些特点

要想理解什么是程序计数器,以及它的特点,需要理解上文中的一句话
这里重点理解 :程序计数器,可以看做是当前线程执行的字节码的 行号指示器 ,这句话;要理解这句话,需要先知道字节码文件长什么样子,看下面的代码

// java 文件被翻译为字节码的时候,字节码大概类似于下面的样子
public void haha(){
// 原来的 haha 方法内部的 java 代码,被翻译为下面的类似于汇编语言的指令
0 xxxx ....
2 xxxx ....
4 xx ...
5 xxx ...
}

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

理解了程序计数器,就好理解它的这些特点了;

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

我们想象下,CPU是怎么知道记住之前A线程,执行到哪一处的?

答案是,CPU根本就不会记住之前执行到哪里了,它只是埋头苦干;那是什么保证了切换线程的程序可以正常执行的;答案是 : 程序计数器 ;程序计数器里面保存的是 当前线程执行的字节码的行号(看着像行号,其实是指令地址);

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

那么程序计数器,什么时候分配内存呢?我们试想下,一个线程在执行的任何期间,都会失去CPU执行权,因此,我们要从一个线程被创建开始执行,就要无时无刻的记录着该线程当前执行到哪里了!因此,线程计数器,必须是线程被创建开始执行的时候,就要一同被创建; ;

程序计数器,保存的是当前执行的字节码的偏移地址(也就是之前说的行号,其实那不是行号,是指令的偏移地址,只是为了好理解,才说是行号的,),当执行到下一条指令的时候,改变的只是程序计数器中保存的地址,并不需要申请新的内存来保存新的指令地址;因此,永远都不可能内存溢出的;因此,jvm虚拟机规范,也就没有规定,也是唯一一个没有规定 OutOfMemoryError 异常 的区域; ;

当线程执行的是本地方法的时候,程序计数器中保存的值是空(undefined);原因很简单:本地方法是C++/C 写的,由系统调用,根本不会产生字节码文件,因此,程序计数器也就不会做任何记录 ;
————————————————
版权声明:本文为CSDN博主「淮左白衣」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/youngyouth/article/details/79868299

jvm运行时数据区之程序计数器的更多相关文章

  1. JVM 运行时数据区:程序计数器、Java 虚拟机栈和本地方法栈,方法区、堆以及直接内存

    Java 虚拟机可以看作一台抽象的计算机,如同真实的计算机,它也有自己的指令集和运行时内存区域. Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存(运行时内存区域)划分为若干个不同的数 ...

  2. Jvm运行时数据区

    一:运行时数据区 Java虚拟机在执行Java程序的过程中会把它管理的内存分为若干个不同的数据区域.这些区域有着各自的用途,一级创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户 ...

  3. Java内存管理:Java内存区域 JVM运行时数据区

    转自:https://blog.csdn.net/tjiyu/article/details/53915869 下面我们详细了解Java内存区域:先说明JVM规范定义的JVM运行时分配的数据区有哪些, ...

  4. JVM 运行时数据区 (三)

    JVM运行时数据区 运行时数据区由 程序计数器.java虚拟机栈.本地方法栈.堆.方法区 组成: 1.程序计数器 每一个Java线程都有一个程序计数器,用于保存程序执行到当前方法的哪一个指令,它是线程 ...

  5. JVM总结(一):概述--JVM运行时数据区

    大三下,趁着寒假重温一遍JVM,准备在一个系列来总价一下学习JVM的整个过程.争取在接下来的一个星期内更新完这一个系列,然后回家过年. JVM运行时数据区 线程私有的数据区 程序计数器 虚拟机栈 本地 ...

  6. JVM运行时数据区与JVM堆内存模型小结

    前提 JVM运行时数据区和JVM内存模型是两回事,JVM内存模型指的是JVM堆内存模型. 那JVM运行时数据区又是什么? 它包括:程序计数器.虚拟机栈.本地方法栈.方法区.堆. 来看看它们都是干嘛的 ...

  7. JVM运行时数据区和垃圾回收机制

    最近参考各种资料,尤其是<深入理解Java虚拟机 JVM高级特性和最佳实践>,大牛之作.把最近学习的Java虚拟机组成和垃圾回收机制总结一下. 你不会的都是新知识,学无止境,每天进步一点点 ...

  8. Java中的字符串常量池和JVM运行时数据区的相关概念

    什么是字符串常量池 JVM为了减少字符串对象的重复创建,其维护了一个特殊的内存,这段内存被成为字符串常量池或者字符串字面量池 工作原理 当代码中出现字面量形式创建字符串对象时,JVM首先会对这个字面量 ...

  9. JVM运行时数据区及对象在内存中初始化的过程

    JVM运行时数据区 Java虚拟机所管理的内存区域,也称为运行时数据区,分为以下几个运行时数据区,如图所示 程序计数器:当前程序所执行字节码的行号指示器 程序计数器(Program Counter R ...

随机推荐

  1. [Tkinter 教程12] 布局管理 (Pack Place Grid)

    简介: 本文讲述如何使用 tkinter 的布局管理 (被称作 layout managers 或 geometry managers). tkinter 有三种布局管理方式: pack grid p ...

  2. USACO Score Inflation

    洛谷 P2722 总分 Score Inflation https://www.luogu.org/problem/P2722 JDOJ 1697: Score Inflation https://n ...

  3. pycharm初爬虫

    今天尝试使用pycharm+beautifulsoup进行爬虫测试.我理解的主要分成了自己写的HTML和百度上的网页两种吧.第一种,读自己写的网页(直接上代码): (主要参考博客:https://bl ...

  4. pinpoint 安装指南

    tangcheng@ChenTang MINGW64 /c/Developer $ git clone https://github.com/naver/pinpoint.git Cloning in ...

  5. day 22

    Creativity requires the courage to let go of certainties. 创新需要勇气承担不确定性.

  6. 第09组 Beta冲刺(2/5)

    队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 学习 展示GitHub当日代码/文档签入记录 接下来的计划 完成短租车,页面美化 还剩下哪些任务 ...

  7. Export failed for github.com/hashicorp/consul: Unable to export source: exit status 128

    背景 go项目,使用glide install命令去下载安装依赖,依赖中有个github.com/hashicorp/consul 问题描述 一直无法下载安装依赖成功,报错如下: [ERROR] Ex ...

  8. 微信小程序绑定列表数据

    js代码 Page({ /** * 页面的初始数据 */ data: { words:[] } wxml代码 <view wx:for="{{words}}" class=' ...

  9. (十五)golang--init函数

    每一个源文件都会包含一个init函数,这个函数会在执行main()执行之前被调用,相当于python中的__init__ 注意细节:(1)如果一个文件同时包含全局变量定义,init函数和main函数, ...

  10. markdown文本内跳转

    Markdown文本内跳转 构建茅的过程中使用markdown语法,类似于markdown向外跳转链接,目的地地址写成#. 在markdown文本中写入: 目录 跳转 跳转部分按照html文本的写法 ...