前言
JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
运行时数据区域
Java虚拟机在执行程序的过程中会把它所管理的内存划分为几个区域,每个区域各司其职,先从整体上来把握一下各个区域
注:上图空间大小不代表各个区域大小的比例
暂且把上面的各个部分分为绿色和红色、其中绿色部分是线程共享的,红色部分是线程隔离的(也就是说红色区域的对象不会有线程安全问题)。各个区的作用如下:
- 程序计数器(Program Counter Register):线程私有,是一块比较小的内存空间,作用相当于当前线程执行字节码的行号指示器。字节码解释器通过改变这个计数器的值来选取下一条需要执行的字节码指令。分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。如果线程执行的是一个Java方法,计数器记录的是正在执行的虚拟机字节码指令地址,如果是Native方法这个计数器的值为Undefined。此区域是Java虚拟机规范中唯一一个没有定义任何OutOfMemoryError情况的区域
- 虚拟机栈(VM Stack):线程私有,生命周期与线程相同,描述的是Java方法执行的内存模型。每个方法执行的时候都会创建一个栈帧(Stack Frame)用于存储局部变量表,操作栈、动态链接、方法出口等信息。每一个方法被调用直至完成,对应一个栈帧在虚拟机栈中从入栈到出栈的过程。Java虚拟机规范对此区域定义了两种异常:如果请求栈的深度大于虚拟机所允许的深度,则会抛出StackOverflowError;如果虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存,会抛出OutOfMemoryError。
- 本地方法栈(Native Method Stack):线程私有,功能与虚拟机栈类似。只不过虚拟机栈为Java方法服务,而本地方法栈为Native方法服务,HotSpot虚拟机(sun JDK自带的虚拟机)将虚拟机栈和本地方法栈合二为一了。
- 方法区(Method Area):线程共享,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,Java虚拟机规范把方法区描述为堆的一个逻辑部分。HotSpot虚拟机在JDK1.7以及之前的版本用永久代(PermGen)实现了方法区,JDK1.7之后使用元空间(MetaSpace)实现方法区。
- 堆区(Heap):线程共享,是Java虚拟机所管理的内存中最大的一块。几乎所有的对象实例都在这里分配内存。堆区也是GC管理的主要区域。如果堆中没有内存可以分配实例,并且堆也无法再扩展时,会抛出OutOfMemoryError异常。
总结
以上就是sun JDK中虚拟机的内存粗略划分以及各个区域的作用,了解区域划分是理解Java虚拟机的第一步。
参考
《深入理解Java虚拟机》