jvm整体结构与内存模型
2020-09-22 20:33:58 3 举报
jdk8中,从一个类加载到对象的创建,整个过程中在jvm内存模型中的区域划分与走向,涉及到对象创建(对象头),jvm内存模型(堆栈,元空间等)、类加载机制
作者其他创作
大纲/内容
LiBo
局部变量表
字节码解释器
Math类信息
堆中分配内存
解析
在Jdk8后完全使用本地内存中实现的元空间(Meta-space)来代替
初始化
class对象
数组长度
window系统下java.exe调用底层的jvm.dll文件创建java虚拟机(C++实现)
C++调用java代码创建jvm启动器实例sun.misc.Launcher,该类为引导类加载器加载并创建其他加载器
验证
是
虚拟机栈(线程栈)
类装载子系统
动态连接
Mark Word
从概念上讲,这些类变量所使用的内存都应当在方法区中进行分配,但必须注意到方法区本身是一个逻辑上的区域,在JDK 7及之前,HotSpot使用永久代来实现方法区时,实现是完全符合这种逻辑概念的;而在JDK 8及之后,类变量则会随着Class对象一起存放在Java堆中,这时候“类变量在方法区”就完全是一种对逻辑概念的表述了
C++实现
klass pointer
像native方法
ss
基本数据类型、对象引用、returnAddress类型(指向了一条字节码指令的地址)
连接(Linking)
方法区(元空间)
sun.misc.Launcher无参构造方法创建实例
c = 123;
对齐填充
getLauncher()
static Object a = new Object();
实例数据
直接内存
堆
执行<init>方法
klass对象
3:在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口
内存空间(但不包括对象头)都初始化为零值
准备
操作数栈
用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据
方法出口
类加载检查
栈帧
对象头
程序计数器
test.Math
加载
执行<init>方法
每个线程都是自己的程序计数器
parent
Math对象
static int b = 123;
应用程序类(app)加载器
设置对象头
本地方法栈
java实现
加载我们的Math类
Object a=null;
创建一个引导类加载器实例(C++实现)
引导类加载器
对类的静态变量初始化为指定的值,执行静态代码块
static final int c = 123;
解析阶段是Java虚拟机将常量池内的符号引用替换为直接引用的过程
分配内存
已分配给Math
object对象
1:通过类的全限定名来获取定义此类的二进制字节流
否
是否已加载类
虚拟机访问
2:将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
扩展类(ext)加载器
程序员访问
首先将去检查这个指令的参数(无参构造的话只有一个new指令,参数为自己类,有参的话有多少个就有多少个new、dup、invokespecial指令)是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那必须先执行相应的类加载过程。
加载类
校验字节码文件的正确性
类变量
从常量池定位new指令参数的类
记录指令行号
“几乎”所有的对象实例都在这里分配内存
类变量分配内存并设置类变量初始值的阶段
空内存
b = 0;
双亲委派机制
b = 123;
0 条评论
回复 删除
下一页