包括类装载子系统,执行引擎,本地方法接口,运行时数据区
运行数据区包括:方法区,堆,Java栈,PC寄存器,本地方法栈
方法区:
被装载类型的信息存储在一个逻辑上被称为方法区的内存中。JVM加载class文件,创建方法区,改类中的类型信息,类(静态)变量存在于此。
类型信息包括:
这个类型的全限定名
这个类型的直接超类的全限定名(java.lang.Object除外)
这个类型的类类型还是接口类型
这个类型的访问修饰符(public/abstract/final等等)
任何直接超接口的全限定名的有序列表
除了上面的基本类型信息外,还保存:
该类型的常量池(包括直接常量,如string,integer,floating point常量,和对其他类型、字段和方法的符号引用)
字段信息(字段名、字段类型、字段修饰符)
方法信息(方法名、方法返回类型、参数变量和类型、方法修饰符)
除了常量以外的所有类(静态)变量
一个到类ClassLoader的引用
一个到Class类的引用
所有线程共享方法区。
方法区大小不必固定、连续,可动态调整。方法区可以在堆中自由分配,另外,JVM也可以允许用火或程序员指定方法区的初始大小及最大、最小值。
方法区可以被垃圾回收。
堆:
Java程序在运行时创建的所有类实例或数组放与此。每创建一个JVM实例就有一个堆,该实例的所有线程都共享这个堆。
Java对象中包含的基本数据由它所属的类及其所有超类声明的实例变量组成。只要有对对象引用,虚拟机就必须快速定位对象实例的数据。另外,他也必须能通过该对象引用访问相应的类数据(存储于方法区的类型信息)。因此在对象中通常会有一个指向方法区的指针。
一种可能的堆空间设计就是,把堆分为两部分:一个句柄池,一个对象池。一个对象引用就是一个指向句柄池的本地指针。句柄池的每个条目有两部分:一个指向实例变量的指针,一个指向方法区类型数据的指针。这种方法有利碎片整理。
另一个设计方式是使对象指针直接指向一组数据,而该数据包括对象实例数据以及指向方法区中的类数据指针。因此只需一个指针就可以访问对象的实例数据。
Java栈:
每启动一个新线程,JVM为其分配一个Java栈。其使用帧为单位保存线程的运行状态。
Java栈存储每个线程中Java方法调用的状态—包括局部变量,被调用时传进来的参数,返回值,运算中间结果。
每当线程调用一个Java方法时,虚拟机都会在该线程的Java栈中压入一个新帧。而这个新帧成为当前帧。在执行这个方法时,它使用这个帧来存储参数、局部变量、中间运算结果等等数据。
Java栈不连续,可指定初始大小和最大最小值。
本地方法栈:
前面提到的所有运行时数据区都是Java虚拟机规范中明确定义的,除此之外,对于一个运行中的Java程序而言,它还能会用到一些跟本地方法相关的数据区。当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。本地方法可以通过本地方法接口来访问虚拟机的运行时数据区,不止与此,它还可以做任何它想做的事情。比如,可以调用寄存器,或在堆中分配内存等。