在接头JVM内存区域阐明之前,先来看一下Java措施详细执行的进程:
Java 措施的执行进程:Java 源代码文件(.Java文件)-> Java Compiler(Java编译器)->Java 字节码文件(.class文件)->类加载器(Class Loader)->Runtime Data Area(运行时数据)-> Execution Engine(执行引擎)。 我们本日就来阐明一下Java措施执行进程的 Runtime Data Area(运行时数据) 这一块
那么运行时数据区包罗哪几部门呢?
一、措施计数器
用来指示措施执行哪一条指令,这跟汇编语言的措施计数器的成果在逻辑上是一样的。JVM类型中划定,假如线程执行的长短native要领,则措施计数器中生存的是当前需要执行的指令地点,假如线程执行的是native要领,则措施计数器中的值undefined。每个线程都有本身独立的措施计数器。为什么呢?因为多线程下,一个CPU内核只会执行一条线程中的指令,因此为了使每个线程在线程切换之后可以或许规复到切换之前的措施执行的位置,所以每个线程都有本身独立的措施计数器。
二、Java虚拟机栈
Java虚拟机栈中存放的是一个个栈帧,当措施执行一个要领时,就会建设一个栈帧并压入栈中,当要领执行完毕之后,便会将栈帧移除栈。我们所说的“栈”是指Java虚拟机栈,一个栈帧中包罗:局部变量表、操纵数栈、动态毗连、要领返回地点、附加信息
局部变量表
主要是存储要领中的局部变量,包罗要领中局部变量的信息和要领的参数。如:各类根基数据范例(boolean、byte、char、short、int、float、long、double)、工具引用(reference范例,它不等同于工具自己,大概是一个指向工具起始地点的引用指针,也大概是指向一个代表工具的句柄或其他与此工具相关的位置)和returnAddress范例(指向了一条字节码指令的地点),个中64位长度的long和double范例的数据会占用2个局部变量空间(Slot),其余的数据范例只占用1个。局部变量表的巨细在编译器就可以确定其巨细了,因此在措施执行期间局部变量表的巨细是不会改变的。在Java虚拟机类型中,对这个区域划定了两种异常状况:假如线程请求的栈深度大于虚拟机所答允的深度,将抛出StackOverflowError异常;假如虚拟机栈可以动态扩展(当前大部门的Java虚拟机都可动态扩展,软件开发,只不外Java虚拟机类型中也答允牢靠长度的虚拟机栈),假如扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。
操纵数栈
虚拟机把操纵数栈作为它的事情区,措施中的所有计较进程都是在借助于操纵数栈来完成的,大大都指令都要从这里弹出数据,执行运算,然后把功效压回操纵数栈。
动态毗连
每个栈帧都包括一个指向运行时常量池中该栈帧所属要领的引用(指向运行时常量池:在要领执行的进程中有大概需要用到类中的常量),持有这个引用是为了支持要领挪用进程中的动态毗连
要领返回地点
当一个要领执行完毕之后,要返回之前挪用它的处所,因此在栈帧中必需生存一个要领返回地点。
附加信息
虚拟机类型答允详细的虚拟机实现增加一些类型里没有描写的信息到栈帧中,譬喻与高度相关的信息,这部门信息完全取决于详细的虚拟机实现。在实际开拓中,一般会把动态毗连,要领返回地点与其它附加信息全部归为一类,称为栈帧信息。
三、当处所法栈、
当处所法栈(Native Method Stack)与虚拟机栈所发挥的浸染长短常相似的,它们之间的区别不外是虚拟机栈为虚拟机执行Java要领(也就是字节码)处事,而当处所法栈则为虚拟机利用到的Native要领处事。与虚拟机栈一样,当处所法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。
四、堆(heap)
在C语言中,措施员可以通过malloc函数和free函数在堆上申请和释放空间。那么在Java中是怎么样的呢?Java中的堆是用来存储工具自己的以及数组(虽然,数组引用是存放在Java栈中的),险些所有的工具实例都在这里分派内存。在Java中,措施员根基不消去体贴空间释放的问题,软件开发,Java的垃圾接纳机制会自动举办处理惩罚。别的,软件开发,堆是被所有线程共享的,在JVM中只有一个堆。
五、要领区
要领区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、以及编译器编译后的代码等。运行时常量池(Runtime Constant Pool)是要领区的一部门。Class文件中除了有类的版本、字段、要领、接口等描写信息外,尚有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各类字面量和标记引用,这部门内容将在类加载后进入要领区的运行时常量池中存放。在JVM类型中,没有强制要求要领区必需实现垃圾接纳。许多人习惯将要领区称为“永久代”,是因为HotSpot虚拟机以永久代来实现要领区,从而JVM的垃圾收集器可以像打点堆区一样打点这部门区域,从而不需要专门为这部门设计垃圾接纳机制。不外自从JDK7之后,Hotspot虚拟机便将运行时常量池从永久代移除了。