Fork me on GitHub

Java虚拟机之JVM运行时数据区

概述

Java虚拟机在执行Java程序时会将其所管理的内存区域分成几个不同的部分,这几个部分的生命周期以及作用都各自不同,这些区域分别为:方法区(Method Area)、堆(Heap)、虚拟栈(VM Stack)、本地方法栈(Native Method Stack)、程序计数器(Program Counter Register),下面分别详细介绍一下。

运行时线程之间相互隔离的数据区域

  • 虚拟机栈
  • 本地方法栈
  • 程序计数器

虚拟机栈

虚拟机栈属于线程私有,其生命周期与线程保持一致。VM Stack描述的是一个Java方法执行 时的内存模型。每个方法在执行时都会创建一个栈帧,这个栈帧会存储方法的局部变量表、操作数栈、方法出口等信息。一个Java方法从运行到结束,对应于一个栈帧从虚拟机栈入栈到出栈的过程。这里的局部变量表存放了各种基本类型(比如int、float等)、还有对象引用。Java方法运行时,局部变量表是不会改变的,因为VM Stack中需要对正要运行的方法创建多大空间的栈帧是确定的。但如果线程请求的栈帧空间大于VM Stack时就会抛出OOM异常。

本地方法栈

本地方法栈与VM Stack的作用基本相同,部分虚拟机并没有按照Java虚拟机规范分开两者,像HotSpot虚拟机就将二者合起来。

程序计数器

程序计数器属于线程私有空间,可以认为程序计数器就是一个当前正在执行的字节码的行号指示器,虚拟机的字节码解释器就是通过改变这个计数器的值来选择吓一条需要执行的指令,比如分支语句、循环语句、跳转语句、异常等等都需要依赖程序计数器完成。不同于操作系统的多线程模型,JVM的多线程是依赖于抢占CPU执行时间来完成,也就是说任何时刻,一个CPU核心只会执行一个线程中的指令,因此,为了线程切换之后程序能回到正确的指令处理位置,每个线程都需要一个独立的程序计数器。如果程序正在执行的是一个Java方法,则程序计数器记录的是正在执行的字节码的指令地址,如果正在执行的是一个native方法呢,其值为空(Undefined)。Java虚拟机规范里面,程序计数器是唯一一个不会有OOM的区域。

运行时线程之间共享的数据区域

  • 方法区

方法区

用于存储已经被虚拟机加载的类信息、常量、静态变量等。

Java Heap 是虚拟机管理的内存区域中最大的一块了。Java堆在虚拟机启动时创建,并被所有线程所共享。这个Java堆呢,只用于存放对象实例,理论上所有的对象实例都在这里分配内存。因为堆区是垃圾收集器所关注的主要区域,而现在的很多垃圾收集器都采用分代收集算法,所有Java堆还可以细分为新生代和老年代。

-------------本文结束感谢您的阅读-------------
坚持技术分享,您的支持将鼓励我继续创作!