虚拟机
2021-08-31 17:25:22 1 举报
深入jvm虚拟机
作者其他创作
大纲/内容
1、遇到new:new关键字实例化对象getstatic:读取类的静态字段putstatic:设置类的静态字段invokestatic:调用类的静态方法(直接定义这个类的常量被使用,super class常量引用,初始化superclass,而不会初始化subclass)2、使用java.lang.reflect3、类初始化时,父类没有初始化,则优先初始化父类4、指定主类(包含main方法类)优先初始化5、1.7动态语言java.lang.invoke.MethodHandle
复制算法空间浪费
CMS
Java线程
栈帧
Java堆
CPU2
CPU3
GC线程2
常量池定位符号引用,检查引用类是否被加载、解析和初始化,如果没有,则需要进行加载
长期存活对象进入老年代
Serial
本地方法栈Native Method Stack
this
启动类加载Bootstrap ClassLoad
类型
名称
数量
u1
tag
1
u4
bytes
length
存活对象复制
Tenured generation
完成3件事1、通过一个类的全限定名来获取此类的二进制字节流2、将这个字节流代表的静态数据结构转换成方法区的运行时数据结构3、内存中生成代表这个类的java.lang.Class对象,作为方法区各种数据的访问入口二进制字节,可以是文件,网络来源非数组类加载方式:系统提供的引导类,用户自定义的类(重写类加载器的loadClass()方法)数组类由虚拟机直接创建,数组类的元数据类最终还是由类加载器加载
操作数栈
新生代采取复制算法暂停所有用户线程
Stop The World
线程隔离的数据区
……
object 1
CPU1
用户线程1
程序计数器Program Counter Register
安全点
基于栈的解释器执行过程
确定在运行时,可确定、不变的运行版本,此类方法的调用,称为解析(编译器可知,运行期不可变)静态方法、私有方法、父类方法、实例构造方法类加载阶段把符号引用解析为该方法的直接引用(还有final方法)解析是一个静态过程,在编译时就确定
线程(Thread)
GC线程3
对象实例数据
对象的内存布局
Parallel Old
动态链接
标记
老年代采用标记整理算法暂停所有用户线程
用户线程3
Java栈本地变量表
1、字面量:文本字符串,final常量值2、符号引用:类和接口的全限定名,字段的名称和描述符,方法的名称和描述符虚拟机运行,先从常量池获得对应的符号引用,再在类创建时或运行时解析、翻译到具体的内存地址中
最终标记
Survivor空间
用户线程2
u2
index
int
tag值为7index指向字符串字面量的索引
并发标记
内存在实例化一个Class对象
安全区域
栈顶
类通过类加载器实现类的加载动作,两个类加载器不一致,则两个类必然不相同
类索引查找过程
本地方法库
应用程序类加载器
GC线程
volatile变量特殊规则
SafePoint
3
基于栈的字节码执行引擎
#1 CONSTANT_Class_info
index:2
当前栈帧Current Stack Frame
栈帧n
栈帧2
栈帧1
标记-清除算法内存不规整
java堆内存是否规整1、是,指针碰撞分配方式,Serial、ParNew等使用(Compact过程收集器)2、否,空闲列表分配方式,CMS等使用(Mark-Sweep算法收集器)并发指针安全,1、CAS+失败重试机制2、本地线程分配缓冲(TLAB)
Serial Old(MSC)
Parallel Scavenge
object 2
枚举根节点
CPU0
标记-整理算法
类型指针
方法退出:1、正常完成出口,2、异常完成出口,无返回值
堆heap
字段和方法的描述符字段类型,参数、以及返回值
GC线程1
1、文件格式验证,如魔数,版本等2、元数据验证,语义分析,以保证其描述的信息符合Java规范
存活对象
堆Heap
连接
虚拟机栈VM Stack
用户线程4
垃圾回收算法
对象优先在Eden分配
可达性分析算法
Serial OldSerial的老年代版本
局部变量表
1、处理器乱序执行,指令重排
清理
筛选回收
运行时栈帧结构:虚拟机栈的栈元素栈顶帧才有效
JDK1.7动态类型
Minor GC
初始标记,标记GC Roots
finalize()
并发标记,GC Roots Tracing
short
每个栈帧都包含一个执行运行时常量池的改帧所属方法的引用 调用过程中的动态链接。静态解析,动态链接
引用计数法
内存分配
JMM屏蔽硬件与系统内存访问差异
老年代
tag值为11index指向类或者接口描述符CONSTANT_Class_info索引项index指向类或者接口描述符CONSTANT_NameAndType索引项
偏移 助记符 0: bipush 100 2:istore_1 3:sipush 200 6:istore_2 7:sipush 300 10:istore_3 11:iload_1 12:iload_2 13:iadd 14:iload_3 15:imu1 16:ireturn
执行引擎
object 4
tag值为6按照高位在前存储的double值
8
运行时数据区
堆垃圾回收
虚拟机字节执行引擎
属性名称
使用位置
含义
Code
ConstantValue
Deprecated
Exception
EnclosingMethod
tag值为5按照高位在前存储的float值
0
1、虚拟机栈中引用的对象2、方法区中类静态属性引用对象3、方法区常量引用的对象4、本地方法JNI引用的对象
方法出口
reference
ParNew
两次标记:1、没有GC Roots引用链2、finalize()标记后进入F-Queue
次版本号
100
object 3
GC线程4
解析
本地接口库
1、运行期执行主体检查
Parallel ScavengeParallel Old
空间不足
内存前部
没有volatile和transient
JDK1.8之前虚拟机运行数据区
内存
this_class
value:1
本地方法栈Native methodstack
边界清理垃圾
线程2
Survivor空间不足,使用分配担保,进入老年代
方法调用不等于方法执行,此阶段任务为确定调用方法的版本,暂不涉及方法内部具体运行过程
是否数组类型
GC后空间,不足以存放对象
access_flags
name_index
descriptor
attributes_count
attribute_info
attributes
GC Root sets
1、抢先式中断2、主动式中断,标记中断位置
object 5
垃圾收集器
tag表示位,区分常量类型;name_index,是一个索引值,指向常量池中的CONSTANT_Utf8_info类型常量,表示类的全限定名
tag为1名称length,utf-8编码字符串占用的字节数后面length字节的utf8缩略编码表示的字符串
tag值为9index指向类或者接口描述符CONSTANT_Class_info索引项index指向类或者接口描述符CONSTANT_NameAndType索引项
实例池
当前线程
u1,u2,u3,u4,表示1字节,2字节,3字节,4字节复合数据类型,表习惯_info表示
加载
object 7
直接内存Direct Memory
使用
初始标记GC Roots
线程共有
线程独有
数组类的可见性与组件的可见性一致,不是引用类型,则默认为public
理解GC日志
执行<init>方法,赋程序值
线程n
进程(Process)
u8
内存A
CMS收集器
程序计数器
magic
minor_version
major_version
constant_pool_count
cp_info
constant_pool
constant_pool_count-1
super_class
interface_class
interfaces
访问标识符,如pubblic、private等
对象类型数据
实例化时,JVM为其分配内存来存放自己以及父类继承的变量,在为这些实例变量分配内存时,这些实例变量会被赋零值,内存分配完成后JVM才会对新创建对象程序给定的赋值
2
Mark Word
主版本号
假设类被public声明:则此标志为:0x0001|0x0020=0x0021
方法区
句柄访问对象
方法区Method Area
回收
Java内存模型
标志
描述
CONSTANT_Utf8_info
utf8编码字符串
CONSTANT_Integer_info
CONSTANT_Float_info
4
CONSTANT_Long_info
5
CONSTANT_Double_info
6
CONSTANT_Class_info
7
CONSTANT_String_info
CONSTANT_Fieldref_info
9
CONSTANT_Methodref_info
10
CONSTANT_InterfaceMethodref_info
11
CONSTANT_NameAndType_info
12
CONSTANT_MethodHandle_info
15
表示方法句柄
CONSTANT_MethodType_info
16
表示方法类型
CONSTANT_InvokeDynamic_info
18
标识一个动态调用点
运行时常量池Runtime Constant Pool
新生代
元空间Metaspace
可在编译、运行时确定1、静态分配,依赖静态类型来定位方法执行版本的分派动作,典型的为方法重载2、动态分派,重要体现就是方法重写
验证
对齐填充(Padding)无实际意义,用于占位符
到对象类型数据的指针
并发清除
类加载检查
NIO使用Native函数直接分配对外内存,然后通过JAVA对中的DirectByteBuffer对象作为这块内存的引用进行操作
double
常量池的项目类型
Serial,客户端使用比较多,因为效率低
初始标记
tag值为3按照高位在前存储的int值
句柄池
常量数量
常量池中的符号引用转换成直接引用1、符号引用:任何字面量,可无歧义定位到目标2、直接引用:直接指向目标的指针,相对偏移量或定位到目标的句柄A、类或接口的解析B、字段解析C、类方法解析D、接口方法解析
整理
标记-整理,标记-清理
JDK1.8之前内存分布
对象头(Header)
重新标记,修正标记记录
Class文件格式
内存间相互操作
自定义类加载器
是一组变量值存储空间,用于存放方法参数和方法内部局部变量Code属性中的max_locals定义了分布的局部变量表的最大空间局部变量表以变量槽(slot)为最小单位,long、double进行两次32位读写使用索引方法使用变量表
到对象实例数据的指针
Save和Load操作
提高性能,使用虚方法表,方法表存放着方法的实际入口,没有重写则为父类的方法地址,如果重写,子类指向子类的方法入口,父类指向父类的方法地址在初始化时初始化虚方发表内联缓存方法,类型继承关系分析的守护内联
大对象进入老年代:典型的很长的字符串以及数组
object 6
1、volatile可视为轻量级同步机制2、volatile变量两种特性:保证此变量对所有线程可见性,禁止指令重排序
对象必要设置
包含类级实例以及实例级变量
GC Roots
加载完成二进制字节类到方法区中
内存B
JDK1.8之后内存分布
Java 虚拟机栈:线程私有,java虚拟机栈的生命周期和线程相同描述了java方法执行的线程内存模型:每个方法被创建时,java虚拟机会同步创建一个栈帧
代表字段的简单名称
初始化
1、默认开启线程数:(CPU数量+3)/42、Concurrent Mode Failure导致Full GC3、标记-清理,导致碎片
重新标记
#2 CONSTANT_Utf8_info
length:29
bytes:**/**/**
长期存活的对象
public int add(){ int a = 10; int b = 20; int c = 30; return (a+b)*c;}
复制算法
线程共享,存放绝大部分的实例对象,垃圾管理的主要区域
上面为新生代收集器下面为老年代收集器
分派
G1
为类变量分配内存并设置初始值,数据值0,如果是final字段,则赋值,public static final intvalue=123,赋值为123
操作栈
在使用对象时,JVM首先检查相关类型是否加载过并初始化,如果没有,则JVM立即调用类的构造器完成初始化,初始化后在根据具体情况实例化
1、并行并发2、分代收集3、空间整合4、可预测停顿堆中独立的大小相同的RegionRemembered Set 避免全堆扫描
垃圾回收
初始化零值(不包含对象头)
new命令
并发清理
方法区Method area
java.lang.invoke
对象定位,通过栈上的reference数据来操作堆上的具体对象,分为句柄和指针两种方式,HotSpot虚拟机使用指针访问
线程工作内存为主内存的副本,线程对变量的操作都在工作内存执行1、lock2、unlock3、read4、load5、use6、assign7、store8、write指令按顺序执行,但可不连续执行,中间可插入其他命令先行发生原则,用来确定并发环境下是否安全
确定对象是哪个实例
空间担保,检查
Eden空间
float
程序计数器:线程私有,如果线程执行的是Java方法,则记录的是正在执行的虚拟机字节码指令的地址。如果是Native 本地方法,计数器值为空(Undefined),用途1、字节码解释器通过改变程序计数器来读取指令,从而实现代码的控制流程2、多线程环境时记录当前线程执行位置,当线程切换回来知道从哪儿继续执行
-XX:PretenureSizeThreshold大于此值的对象进入老年代
主内存
数组的组件为引用类型,通过加载过程加载,并在加载该组件的类加载器的类名称空间被标识
动态分派实现
标志名称
标志值
ACC_PUBLIC
0x0001
ACC_FINAL
0x0010
ACC_INTERFACE
0x0020
ACC_ABSTRACT
0x0200
ACC_SYNTHETIC
0x0400
ACC_ANNOTATION
0x1000
0x2000
ACC_ENUM
0x4000
比如这个对象属于哪个类,如何找到类元数据信息,对象的GC分代年龄,是否启用偏向锁等对象头内容设置
基于栈的指令集与基于寄存器的指令集
普通对象创建
扩展类加载器Extension ClassLoader
动态类型语言支持
线程共享,存储被虚拟机加载的类信息,常量,静态变量,即时编译后的代码信息等还有一个运行时常量池,包含在编译期生成的字面量和符号引用
由所有线程共享的数据区
虚拟机加载机制
1、强引用2、软引用3、弱引用4、虚引用
tag值为10index指向类或者接口描述符CONSTANT_Class_info索引项index指向类或者接口描述符CONSTANT_NameAndType索引项
确定对象是否还活着
Young generation
解释执行
准备
魔数,magicnumber,0xCAFEBABE
数组类的加载
Java内存模型与线程
双亲委派模型,工作过程:如果一个类加载器收到类加载请求,优先请求委派给父类加载器加载,若父类无法加载则子类加载java.lang.ClassLoader的loadClass()方法
HotSpot虚拟机内存分代
对象OoMap数据结构保存对象引用
分代收集算法
不是引用类型(int[]数组),标记为与引导类加载器关联
主内存与工作内存
引用
卸载
tag值为4按照高位在前存储的float值
0 条评论
回复 删除
下一页