本节是参考《深入理解java虚拟机》,90%引用上面的话术。
1.什么是运行时数据区,运行时数据区又包括哪几个部分,每个部分的功能是什么,在jdk版本迭代时,又对运行时数据区做了哪些改进。
2.jvm在执行java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,已经创建和销毁时间,有的区域随着虚拟机的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。根据《java虚拟机规范(JavaSE)》的规定,java虚拟机所管理的内存分为以下几个部分,如下图所示:
3.程序计数器(Program Counter Register)
他是一块比较小的内存空间,记录当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码的指令,分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个计数器来完成。
由于java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器或者一个内核都只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器。各线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存。
如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器值则为空(Undefined)。
此内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
4.虚拟机栈
虚拟机栈也是线程私有的,它和线程的生命周期一样。它描述了java方法执行的内存模型,如下图:
在java虚拟机规范中,对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展,如果无法申请到足够内存,就会抛出OutOfmemoryError异常
5.本地方法栈
本地方法栈和虚拟机栈类似。只不过虚拟机栈为执行java方法服务,本地方法栈为使用到的navtive方法服务。在虚拟机规范中,对本地方法栈所使用的语言,数据接口,使用方式并没有强制规定,因此可以自由实现他。有的虚拟机,譬如sun HotSpot虚拟机就把本地方法栈和虚拟机栈和二为一。也同样会抛出异常。
6.java堆
java堆是虚拟机所管理的内存中最大的一块。它被所有线程共享一块内存区域,在虚拟机启动创建时,此内存的唯一目的就是存放对象实例。java堆是垃圾收集器管理的主要区域,因此被称为“GC堆”。根据java虚拟机规定,java堆可以处于物理上不连续的的内存空间。在实现时,既可以固定大小,也可以可扩展,当前主流的虚拟机都是按照可扩展来实现的(-Xmx和-Xms).如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常
7.方法区
与java堆一样,是各个线程共享的区域。它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽然java虚拟机把他描述为堆的一部分,但它有一个别名叫做Non-Heap(非堆)。当方法区无法满足内存分配时,也会抛出OutOfMemoryError异常。