JVM原理
2021-02-21 20:14:55 7 举报
一图全解jvm,类加载
作者其他创作
大纲/内容
程序计数器
自下而上委托查看该类是否已经加载过
类型信息类型的常量池字段信息方法信息类加载器的引用Class实例引用方法表
标记清除算法
年龄15
分代收集算法
幸存者s0(1/10)
BootstrapClassLoader启动类加载器
加载
根可达算法
栈帧
G1(并发整理+复制)
类型指针
加载自定义ClassLoader
数组长度
语义分析
本地方法栈
解析
GCC--垃圾回收机制
自上而下进行检查是否含有该类并加载
词法分析
加载jre\\lib\\*.jar等核心类,主要是C++实现
中间代码生成
局部变量表
垃圾判断算法
代码生成
Parelle|Scavenge(并复制)
三色标记算法
使用
对象
CMS(并发清除)
初始化
方法出口
大对象(可设置)会直接进入老年代,年龄达到15或幸存者去中的相同年龄对象总大小>=幸存者空间总和。该年龄的所有对象将会直接进入老年代
实例数据
准备
为静态变量分配内存并初始化默认值
class类的加载过程
TLAB线程私有
方法区(元空间)
类元信息
用于计算时的临时数据存储区,使用load执行将数据加载到此处
字符串常量池
Parelle Old(并整理)
加载classspath下,主要是编译生成的路径下
链接
相互交互
javac编译
新生代(1/3)
卸载
垃圾回收算法
标记整理算法
方法数据
动态链接
helloword.class
MarkWord
线程中的程序计数器
ParNew(并复制)
字面量文本字符串final常量值基本数据类型其他符号引用类和结构的全限定名字段名称和描述符方法名称和描述符
垃圾收集器--连线表示可以搭配使用
标记复制算法
1、由类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并存储在运行时内存区的方法区2、将其转换为一个与目标类型对应的java.lang.Class对象实例3、这个Class对象在日后就会作为方法区中该类的各种数据的访问入口
CodeCacheJIT编译代码产物
幸存者s1(1/10)
动态连接(多态,编译器没有指明运行时才指明对象),指向常量池中的方法引用
操作数栈
运行时数据区(内存模型)=jdk8
引用计数
老年代(2/3)
语法分析
堆heap
字节码执行引擎
记录出栈地址即方法返回地址或者异常地址
CustomClassLoader自定义
静态变量
Serial Old(串整理)
进行final是否合规、类型是否正确、静态变量是否合法等校验操作
ExtClassLoader 扩展类加载器
常量池
解析类的方法确保类与类之间的相互引用正确性,完成内存结构布局
对齐填充-8字节倍数
Serial(串复制)
验证
双亲委派机制:主要是沙箱安全机制、防止核心类库被修改;避免类的重复加载,保证被加载类的唯一性
Eden(8/10)
加载jre\\lib\\ext\\*.jar或-Djava.ext.dirs文件夹下
数组
方法代码
AppClassLoader系统类加载器
对象头
将一个类中所有被static关键字标识的代码统一执行一遍,如果执行的是静态变量,那么就会使用用户指定的值覆盖之前在准备阶段设置的初始值;如果执行的是static代码块,那么在初始化阶段,JVM就会执行static代码块中定义的所有操作。所有类变量初始化语句和静态代码块都会在编译时被前端编译器放在收集器里头,存放到一个特殊的方法中,这个方法就是<clinit>方法,即类/接口初始化方法。该方法的作用就是初始化一个中的变量,使用用户指定的值覆盖之前在准备阶段里设定的初始值。任何invoke之类的字节码都无法调用<clinit>方法,因为该方法只能在类加载的过程中由JVM调用。如果父类还没有被初始化,那么优先对父类初始化,但在<clinit>方法内部不会显示调用父类的<clinit>方法,由JVM负责保证一个类的<clinit>方法执行之前,它的父类<clinit>方法已经被执行。JVM必须确保一个类在初始化的过程中,如果是多线程需要同时初始化它,仅仅只能允许其中一个线程对其执行初始化操作,其余线程必须等待,只有在活动线程执行完对类的初始化操作之后,才会通知正在等待的其他线程。
代码优化
helloword.java
0 条评论
回复 删除
下一页