java虚拟机 内存分配

分为以下几个运行时数据区:

  程序计数器,java虚拟机栈,本地方法栈,java堆,方法区

程序计数器:

  线程私有,记录正在执行的虚拟机字节码指令地址,执行本地方法则为空,是唯一一个java虚拟机内存中没有PutOfMemoryError情况

java虚拟机栈:

  线程私有,生命周期也与线程相同,用于支持虚拟机进行方法调用和方法执行。对执行引擎来讲,只有栈顶的栈帧是有效的,称为当前栈帧,关联的方法为当前方法,所有字节指令都只针对当前栈帧操作。

  有两种异常情况:

    当线程请求的栈帧大于虚拟机所允许的深度,抛出StackOverflowError异常

    虚拟机在动态扩展栈时无法申请到足够的内存空间,抛出OutOfMemoryError异常

  栈帧所存放的信息:

    局部变量表:存放方法参数和方法内部定义的局部变量,存放的数据的类型是编译期可知的各种基本数据类型,对象引用和returnAddress类型(指向一条字节码指定地址),所需内存空间在编译期完成分配,即在java程序被编译成class时就确定了局部变量表的容量,方法运行期间不会改变。32位一个slot,64位连续的两个slot

    操作数栈:

      又称操作栈,最大深度也在编译时确定。32位占一个栈帧,64两个。操作栈为各种字节码指令(加减赋值)提供支持

      java虚拟机的解释执行引擎称为“基于栈的执行引擎”,栈就是指操作栈,也称为java虚拟机试基于栈的。Android基于寄存器,更快,但移植性不好

    动态连接:

      每个栈帧都包含一个指向运行时常量池(在方法区)的该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程的动态连接。

      常量池存在大量符号引用,一部分会在类加载阶段或第一次使用时候转换为直接引用,称为静态解析,另一部分在每次运行期间转化为直接引用,称为动态连接

    方法返回地址:恢复上层方法的局部变量表和操作数栈,有返回值则把它压入调用者栈帧的操作数栈中

本地方法栈:

  与java虚拟机栈非常相似,虚拟机栈为虚拟机执行的java方法服务,本地方法栈为使用到的本地操作系统(Native)方法服务

java堆:

  是虚拟机所管理的内存中最大的一块,是所有线程共享的一块内存区域。几乎所有的对象实例和数组都在这里分配内存,也是垃圾回收器管理的主要区域,也被称为GC堆

方法区:

  所有线程共享,用于存储已经被虚拟机加载的类信息,常量,静态变量,即使编译器编译后的代码等数据,又被称为永久代。

  运行常量池是方法区一部分,用于存放编译器生成的各种字面量和符号引用,和Class文件常量池(类的版本,字段,方法,接口等描述信息)比具有动态性

原文地址:https://www.cnblogs.com/zawjdbb/p/7245924.html