程序计数器(关于java虚拟机内存的那些事)
《深入理解java虚拟机》 读书感悟
作者:淮左白衣
--------------写于2018年4月9日17:44:48
关于java虚拟机内存的那些事之程序计数器
什么是程序计数器?
程序计数器是一块 较小 的内存空间,它可以看做是当前线程所执行的字节码的 行号指示器 ;在虚拟机的概念模型里(仅仅是概念模型,各种虚拟机可能会通过一些更高效的方式去实现),字节码解释器工作时,就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳准、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成 ;
———–摘抄自 周志明版 《深入理解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 写的,由系统调用,根本不会产生字节码文件,因此,程序计数器也就不会做任何记录 ;
参考:
(笔者在读书的时候,并未立马理解程序计数器,看了下面的博文,才有所理解),贴出链接,如果你恰巧读到这里,可以去看下,下文的作者是怎么讲的 ;
程序计数器(关于java虚拟机内存的那些事)的更多相关文章
- 方法区(关于java虚拟机内存的那些事)
<深入理解 java 虚拟机> 读书扩展 作者:淮左白衣 写于 2018年4月13日21:26:05 目录 方法区 图例(方法区中都保存什么) 类型信息 类型的常量池 (即运行时常量池) ...
- java虚拟机栈(关于java虚拟机内存的那些事)
<深入理解 java 虚拟机> 读书扩展 作者:淮左白衣 写于 2018年4月13日16:26:51 目录 文章目录 java虚拟机栈是什么 特点 栈帧 局部变量表 什么时候抛出 `Sta ...
- 总结Java虚拟机内存区域模型
本篇文章主要来总结一下Java虚拟机内存的各个区域,以及这些区域的作用.服务对象以及其中可能产生的问题,作为大家的面试宝典. 首先我们来看一下Java运行时的数据区域,Java虚拟机在执行Java程序 ...
- 一文解析总结Java虚拟机内存区域模型
最近抽空看了一点<深入理解Java虚拟机>,本篇文章主要来总结一下Java虚拟机内存的各个区域,以及这些区域的作用.服务对象以及其中可能产生的问题,作为大家的面试宝典. 首先我们来看一下J ...
- Java虚拟机-内存tips
java虚拟机内存可以分为独占区和共享区. 独占区:虚拟内存栈.本地方法栈.程序计数器. 共享区:方法区.Java堆(用来存放对象实例). 程序计数器 比较小的内存空间,当前线程所执行的字节码的行号指 ...
- Java虚拟机内存分配详解
简介 了解Java虚拟机内存分布的好处 1.了解Java内存管理的细节,有助于程序员编写出性能更好的程序.比如,在新的线程创建时,JVM会为每个线程创建一个专属的栈 (stack),其栈是先进后出的数 ...
- 重读《深入理解Java虚拟机》一、Java虚拟机内存区域的划分
一.Java虚拟机内存区域如何划分 1.Java虚拟机内存区域的划分 区域名称 作用(用途) 类型 特点 虚拟机规定异常情况 内存分配与回收 其他说明 1 程序计数器 指示当前正在执行的字节码指令地址 ...
- 从一道面试题深入了解java虚拟机内存结构
记得刚大学毕业时,为了应付面试,疯狂的在网上刷JAVA的面试题,很多都靠死记硬背.其中有道面试题,给我的印象非常之深刻,有个大厂的面试官,顺着这道题目,一直往下问,问到java虚拟机的知识,最后把我给 ...
- 聊聊Java 虚拟机的“那点事”
本文的使用方法: 这篇文章是一个总结性质的文章,是我在看完<深入理解 Java 虚拟机>后写的(里面可能会有些不准确的地方,欢迎大家指出),本文从头读到尾就是一个虚拟机大部分知识点的框架, ...
随机推荐
- 浅谈无旋treap(fhq_treap)
一.简介 无旋Treap(fhq_treap),是一种不用旋转的treap,其代码复杂度不高,应用范围广(能代替普通treap和splay的所有功能),是一种极其强大的平衡树. 无旋Treap是一个叫 ...
- js小脚本解析后台数据
java代码 List<CodeTableBean> clfsList = StandardCodeTable.getCodeTable("clfs", "& ...
- 读取文件名.cpp
#include <io.h> #include <iostream> #include <string> #include <windows.h> # ...
- IdentityServer4入门五:错误处理
在访问ClientMvc的保护页面时,会跳转到IdentityMvc页面,这时会出现类似下图的错误界面,让人无从入手. 如果你尝试按文字所说的内容去处理.你发现项目已正确设置.其实上面的内容是固定的, ...
- 解析复杂的嵌套数据结构-jsonpath
JsonPath是一种简单的方法来提取给定JSON文档的部分内容. JsonPath有许多编程语言,如Javascript,Python和PHP,Java. JsonPath提供的json解析非常强大 ...
- ML_Review_GMM(Ch10)
Note sth about GMM(Gaussian Mixtrue Model) 高斯混合模型的终极理解 高斯混合模型(GMM)及其EM算法的理解 这两篇博客讲得挺好,同时讲解了如何解决GMM参数 ...
- Tag Tree
Test & Measurement RF RFID DAQ Mixed Signal Instrumentation DSP C# C\C++ JAVA Work Better Git Ma ...
- java数据类型,取值范围,引用类型解析
与javascript不同,Java是强类型语言,在定义变量前需要声明数据类型.主要分两种数据类型:基本数据类型和引用数据类型. 1.基本数据类型分析: 基本数据类型 数值型 整数型 byte字节 ...
- Excel导出问题
问题一:本地导出正常,部署到linux服务器导出文件内容乱码? 解决:修改服务器tomcat配置 server.xml 添加URIEncoding="UTF-8" <Conn ...
- 123457123456#0#-----com.twoapp.mathGame13--前拼后广--13种数学方法jiemei
com.twoapp.mathGame13--前拼后广--13种数学方法jiemei