「每日五分钟,玩转JVM」:线程独占区

前言

若是咱们对计算机组成有所了解,那么咱们必定会知道在计算机中有一起特殊的区域,称之为寄存器,寄存器包括了指令寄存器和程序计数器,这两样位于CPU中,做为程序运行的大脑来控制程序的运行和流转。java

而在JVM中,做为一种虚拟机,JVM没有指令寄存器,它是基于栈 + 程序计数器的体系结构来完成方法的执行,之因此这么去设计一方面是为了指令集的紧凑,一方面是有些平台上的寄存器不多或者根本没有,并且以处理器架构的角度来讲,设计一套通用的寄存器指令是很困难的,并且还有一方面的考量就是有助于运行时某些虚拟机实现的动态编译器和即时编译器的代码优化。多线程

程序计数器

咱们在使用IDE写代码的时候,旁边常常会有行数,方便咱们去阅读咱们本身的代码,去定位咱们代码的位置,而程序计数器是给JVM执行字节码过程当中看的行号指示器,只不过他其中存的并不是是行号,而是执行中虚拟机字节码指令的地址,也正是由于计数器中存储的仅仅是一条执行中的指令地址,使用的内存是及其有限的,因此这个区域是惟一一个没有OOM的区域。字节码解释器经过改变程序计数器中的地址来寻找对应的指令来完成对程序的控制(这里具体咱们会在分析指令集时去详细的深刻了解,这里仅仅点到为止)架构

这里须要注意一点,若是是本地Native 方法,该计数器的值是Undefined,其实也很好理解,人家压根不属于JVM去管理,你凭什么去记录。。这里咱们使用的能够说是Native方法提供出的一个接口,具体的实现是经过C来完成的。优化

上节课咱们说到多线程的实现是基于时分复用来实现的,为了每一个线程的运行的互不干扰和有序性,程序计数器必须保证在切换时可以回到正确的位置,因此它必须必然是线程独占区的一份子。spa

关键字:线程

  • 行号指示器
  • 执行中字节码指令地址
  • 没有OOM
  • Native方法不归他管
  • 线程独享

虚拟机栈

虚拟机栈是Java方法运行时的内存模型,包括了局部变量表,操做数栈,动态链接,方法返回地址以及一些附加信息,每一个方法在被执行的时候会在虚拟机栈中创造一个栈帧设计

image-20190811225812846

栈帧在执行的时候建立压入栈,在彻底执行完成后就会进行弹栈,下面是一个小🌰去直观的看一下过程~3d

carbon

image-20190811232655530

(小声BB一句,这里不会制做GIF图,凑合着看吧。。)code

下面简单介绍一下栈帧中的内容,这一部分咱们会在了解字节码执行引擎的时候会进行更为详细的讲解。cdn

  • 局部变量表

    局部变量表(Local Variable Table)是一组变量值存储空间,用于方法参数和方法内部定义的局部变量,包含了编译器可知的基本数据类型(byte,short,int,long,double,float,char,boolean),对象引用(reference)以及returnAddress类型。

  • 操做数栈

    一样是一个LIFO(Last In First Out,后入先出)的栈结构,用于计算的临时存储区,前面提过JVM是没有寄存器的,而操做数栈的做用就是让JVM的指令是从中获取操做数。

  • 动态链接

    每一个栈帧都包含一个运行时常量池中该栈帧所属方法的引用,持有这个引用就是为了支持方法在调用过程当中的动态链接

本地方法栈

和虚拟机栈类似,本地方法栈面向的对象不是JVM字节码,而是本地的Native方法,好比String类中的intern方法,Native方法更像是本地方法的提供的一个接口,而本地方法栈正是管理这些接口的一个区域。

public native String intern();
复制代码

异常

本地方法栈和虚拟机栈同为栈结构之中,他们会面对两种异常,当线程请求的栈深度大于虚拟机所容许的深度时,将抛出StackOverflowError,若是栈能够动态扩展,若是扩展时没法申请到足够的内存,会抛出OOM异常

公众号

相关文章
相关标签/搜索