01-JVM内存模型:程序计数器

1、JVM模型概述

  java虚拟机(JVM)在java程序运行的过程当中,会将它所管理的内存划分为若干个不一样的数据区域,这些区域有的随着JVM的启动而建立,有的随着用户线程的启动和结束而创建和销毁。一个基本的JVM运行时内存模型以下所示:

  上图展现的是“JAVA SE7”的JVM虚拟机规范。注意,虚拟机规范并非一成不变的,Oracle在发布新的JAVA版本时,可能会对JVM作必定的优化和改进,例如在JDK8的版本中,方法区被移除,取而代之的是metaspace(元数据空间)。java

  在本章及下面的章节中,将以JDK7的标准做为例子,对JVM的运行时数据区进行讲解。

2、程序计数器(Program Counter Register)

2.1)什么是程序计数器

  程序计数器是一个记录着当前线程所执行的字节码的行号指示器。
  JAVA代码编译后的字节码在未通过JIT(实时编译器)编译前,其执行方式是经过“字节码解释器”进行解释执行。简单的工做原理为解释器读取装载入内存的字节码,按照顺序读取字节码指令。读取一个指令后,将该指令“翻译”成固定的操做,并根据这些操做进行分支、循环、跳转等流程。
  从上面的描述中,可能会产生程序计数器是不是多余的疑问。由于沿着指令的顺序执行下去,即便是分支跳转这样的流程,跳转到指定的指令处按顺序继续执行是彻底可以保证程序的执行顺序的。假设程序永远只有一个线程,这个疑问没有任何问题,也就是说并不须要程序计数器。但实际上程序是经过多个线程协同合做执行的。
  首先咱们要搞清楚JVM的多线程实现方式。JVM的多线程是经过CPU时间片轮转(即线程轮流切换并分配处理器执行时间)算法来实现的。也就是说,某个线程在执行过程当中可能会由于时间片耗尽而被挂起,而另外一个线程获取到时间片开始执行。当被挂起的线程从新获取到时间片的时候,它要想从被挂起的地方继续执行,就必须知道它上次执行到哪一个位置,在JVM中,经过程序计数器来记录某个线程的字节码执行位置。所以,程序计数器是具有线程隔离的特性,也就是说,每一个线程工做时都有属于本身的独立计数器。

2.2)程序计数器的特色

  1.线程隔离性,每一个线程工做时都有属于本身的独立计数器。
  2.执行java方法时,程序计数器是有值的,且记录的是正在执行的字节码指令的地址(参考上一小节的描述)。
  3.执行native本地方法时,程序计数器的值为空(Undefined)。由于native方法是java经过JNI直接调用本地C/C++库,能够近似的认为native方法至关于C/C++暴露给java的一个接口,java经过调用这个接口从而调用到C/C++方法。因为该方法是经过C/C++而不是java进行实现。那么天然没法产生相应的字节码,而且C/C++执行时的内存分配是由本身语言决定的,而不是由JVM决定的。
  4.程序计数器占用内存很小,在进行JVM内存计算时,能够忽略不计。
  5.程序计数器,是惟一一个在java虚拟机规范中没有规定任何OutOfMemoryError的区域。
相关文章
相关标签/搜索