JVM内存模型
2020-04-01 11:05:51 0 举报
JVM虚拟机内存区域划分学习
作者其他创作
大纲/内容
方法A-->栈帧 Stack Frame......
运行时常量池--方法区一部分 类的常量池表(用于存放编译期生成的各种字面量和符号引用),这部分内容在类加载后,存放在运行时常量池。 String类intern()方法---运行期间将新的常量放入池中
局部变量表Local Variable Table
1、方法开始执行后,只有 2 种方式可以退出 :方法返回指令,异常退出。2、无论采用何种退出方式,在方法退出之后,都需要返回到方法被调用的位置,程序才能继续执行,方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层方法的执行状态。一般来说,方法正常退出时,调用者的PC计数器的值可以作为返回地址,栈帧中很可能会保存这计数器值。而方法异常退出时,返回地址是要通过异常处理器表来确定的,栈帧中一般不会保存这部分信息。3、方法退出的过程实际上就等同于把当前栈帧出栈,因此退出时可能执行的操作有:恢复上层方法的局部变量表和操作数栈,把返回值(如果有的话)压入调用者栈帧的操作数栈中,调整PC计数器的值以指向方法调用指令后面的一条指令等。
方法B-->栈帧 Stack Frame......
方法区Method Area存储已被虚拟机加载的类信息、常量、静态变量等等内存回收主要目标针对常量池的回收和对类型的卸载
JDK 1.8---之后版本 完全废除永久代的概念---改用在直接内存中实现元空间代替
变量B
1、操作栈---先入后出2、操作数栈的最大深度,在编译的时候已经写入方法表的code属性的max_stacks数据项中。
所有线程共享区域
上图来源:https://blog.csdn.net/wangbiao007/article/details/78545189
变量A
1、每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态链接2、在类加载阶段中的解析阶段会将符号引用转为直接引用,这种转化也称为静态解析。另外的一部分将在运行时转化为直接引用,这部分称为动态链接。3、class文件中存在着大量的符号引用。只有父类方法,静态方法,私有方法,实例构造器可以在代类加载时转化为直接引用。而其他则必须在每一次使用进行一次解析
......
JDK 1.8之前 许多人称之为--永久代 这种设计导致Java程序更容易内存溢出----因此逐渐的开始去永久代 JDK 1.7已经把放在永久代的字符串常量池、静态变量等移出
常量池堆
用于存放方法参数和方法内部定义的局部变量1、在编译程序代码的时候就可以确定栈帧中需要多大的局部变量表,具体大小可在编译后的 Class 文件中看到。2、局部变量表的容量以 Variable Slot(变量槽)为最小单位,每个变量槽都可以存储 32 位长度的内存空间。3、在方法执行时,虚拟机使用局部变量表完成参数值到参数变量列表的传递过程的,如果执行的是实例方法,那局部变量表中第 0 位索引的 Slot 默认是用于传递方法所属对象实例的引用(在方法中可以通过关键字 this 来访问到这个隐含的参数)。其余参数则按照参数表顺序排列,占用从 1 开始的局部变量 Slot。4、基本类型数据以及引用和 returnAddress(返回地址)占用一个变量槽,long 和 double 需要两个。
操作数栈Operand Stack
运行时数据区
动态链接Dynamic Linking
本地方法库
本地方法栈Native Method Stack执行本地方法
HotSpot直接把本地方法栈和虚拟机栈合二为一。本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常
直接内存设置直接内存大小元空间
Java栈
返回地址Return Address
本地库接口
基于栈的执行引擎
线程独占区域
堆Heap唯一目的存放存放对象实例所有对象实例和数组在堆上分配---已经不是绝对(栈上分配,逃逸分析等)
执行引擎
程序计数器Program Counter线程执行的如果是一个Java方法,计数器记录的是正在执行的虚拟机字节码指令的地址,如果执行的是一个native方法,计数器值为空
虚拟机栈VM Stack描述Java方法执行的内存模型生命周期和线程一样每个方法在执行的同时会创建一个栈帧,每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程执行Java方法
0 条评论
下一页