JVM
2021-01-14 11:35:05 0 举报
JVM运行时数据
作者其他创作
大纲/内容
getClass
对象类型数据
存活区-Survivor
解析2.3
Epoch
ParallelScavenge
验证2.1
通过句柄访问对象
实例化
01
F 如Car.java
分代年龄
方法区(D)
STW:Stop the world ,GC停顿
操作压栈
2. 直接访问对象reference 直接指向了对象类型数据,那么java堆对象分布中就必须考虑如何放置访问类型数据的相关信息,reference存储的直接就是对象地址好处就是,减少一次指针定位的时间开销
0
局部变量表
car2
句柄池
ClassLoader
本地方法接口
逃逸分析:就是分析对象动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他的地方中。-XX: +DoEscapeAnalysis// 使用-XX: -DoEscapeAnalysis // 不用一,同步省略,如果一个对象被发现只能从一个线程被访问到,那么对这个对象的操作可以不考虑同步二,将堆分配转换为栈分配,如果一个对象在子程序中将被分配,要使指向该对象的指针永远不会逃逸,对象可能是栈的分配的候选,而不是堆的分配(栈上分配--Hotspot并没有真正意义上的栈上分配,实际上是标量替换)三,分离对象或标量替换。有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分或者全部可以不存储在内存,而是存储在CPU寄存器中。在动态编译同步块的时候,JIT编译器可以借助逃逸分析来判断同步块所使用的锁对象是否只能被一个线程访问而没有发布到其他线程。如果同步块使用的锁对象通过这种分析被证实只能够被一个线程访问,那就优化成锁消除
指向互斥量(重量级锁)的指针
Virtual-伸缩区
parNew
2bit
对象引用: 就是通过栈帧中局部变量表锁存储的对象引用来对堆内存中的对象实例进行访问或操作的,简单点理解就是栈帧中有个对象引用的指针,通过各种方法指向了堆内存中的对象实例
本地方法栈(A)
类加载器子系统classLoad(F)
压栈
加载1
GC标志
23bit
到对象类型数据的指针
Old
1bit
Class.class
class文件
方法区
对象引用(引向E)
1. 线程是用来执行方法的,至于怎么执行,取决于虚拟机栈2. 我们定义的常量和静态常量是存在方法区的,就是用于线程之间共享
1. 指针碰撞: 依靠连续的内存空间,靠指针的移动来分配内存2. 空间列表: 由固定的列表记录内存分配的信息,每一线程执行一块空间。TLAB
来回换
本地方法库,C/C++
1. 句柄java堆中划分出一块内存作为句柄池,reference中存储的是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息句柄访问最大的好处就是reference中存储的是稳定的句柄地址,在对象被移动时,只用修改句柄中的实例数据指针,而reference本身不需要修改
short
空
-XX: MaxPermSize
iload_1
是否偏向锁
对齐填充Padding(保证对象是8个字节的整数倍)
int
To Space
标记-整理
实例池
Java栈本地变量表
1. 程序计数器:指向当前线程正在执行的字节码的地址,行号,线程私有,无GC2. 虚拟机栈:存储当前线程运行方法所需要的数据,指令,返回地址。线程稀有,无GC3. 本地方法栈:同虚拟机栈,不同的是,存储的是本地方法的数据4. 方法区:存储类信息(字段方法的字节码,部分方法的构造器),常量,静态常量,JIT(即时编译的信息)。线程共享,无GC,非堆区5. 堆-heap: 存储类实例,一个jvm实例只有一个堆内存,线程共享,要GCjdk1.6及之前,有永久代,字符串常量池和运行时常量池在方法区jdk1.7:有永久代,但已经逐步“去永久代”,字符串常量池移到堆中,运行时常量池还在方法区(永久代)jdk1.8: 无永久代,字符串常量池在堆中,运行时常量池在元空间
iload_0
Parallel
SerialOld(MSC)
垃圾回收
连接2
-优先分配Eden区* 大对象直接分配到老年代XX:PretenureSizeThreshold* 长期存活的对象分配老年代XX:MaxTenuringTHreshold=15* 空间分配担保XX:+HandlePromotionFailure检查老年代最大可用的连续空间是否大于历次晋升老年代对象的平均大小.* 动态对象年龄对象如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可用直接进入老年代-XX:TargetSurvivorRatio
young都是复制回收
方法出口
float
初始化3
S0
E 堆内存模型
无锁态
标记-清楚算法,减少回收停顿时间, 碎片-XX:CMSSlnitiationOccupancyFraction Concurrent Model Failure 启用Serial Old
Young
32位长度(4b)
对象的访问
执行引擎execution engine
Young Gen (-Xmn)
methodA
偏向锁
使用4
对象实例数据
Serial
10
变量压栈
方法区是一种定义,概念,而所谓的永久代或元空间是其一种实现机制
锁标志位
methodB
类加载的生命周期
标记-整理算法
调用对象的 init 方法
线程ID
JVM
动态链接
double
若未找到引用,则执行类的加载,加载,验证,初始化
一个方法一个栈帧
操作数栈
00
默认
到对象实例数据的指针
根据new的参数在常量池D中定位一符号引用
程序计数器(A)
1.8之前叫永久代
4bit
新生代Young
reference
FromSpace
Eden(伊甸园)
基本类型
JVM运行时数据区
Car实例
分带年龄
对象的hashCode
B
Object
JVM Heap(-Xms -Xmx)
.......
将分配的内存初始化为零值
轻量级锁
Minor GC
虚拟机为对象分配内存E
Old区
new 类名()
指向栈中锁记录的指针
car1
1
实例数据instance data
Car Class(类信息)
堆(E)
ParallelOld
元空间
锁状态
老年代
S1
加载初始化
虚拟机栈(B)
G1
CMS
Java堆
1-加载类文件,从class文件或者jar中,或者从二进制流中,以类全名标识存入方法区,供之后的使用2.1-验证类文件是否符合jvm的规范,验证一些类的基本信息。格式验证,语义分析,操作验证。2.2-准备为类的静态变量和常量分配空间和初始值,在堆中分配空间。2.3-把常量池中的符号引用转为直接引用,可以认为是一些静态绑定的会被解析,动态绑定则只会在运行时进行解析;静态绑定包括一些final方法(不可以重写),static方法(只会属于当前类),构造器(不会被重写)3. 初始化将一个类中所有被static关键字标识的代码统一执行一遍,如果执行的是静态变量,那么就会使用用户指定的值覆盖之前在准备阶段设置的初始值;如果执行的是static代码块,那么在初始化阶段,JVM就会执行static代码块中定义的操作。所有类变量初始化语句和静态代码块都会在编译时被前端编译器放在收集器里,存放在一个特殊的方法中,这个方法就是<clinit>方法,即类/接口初始化方法。该方法的作用就是初始化变量,使用用户指定的值覆盖之前在准备阶段设置的初始值。任何invoke之类的字节码都无法调用<clinit>方法,因为该方法只能在类加载的过程中由JVM调用。如果父类没有被初始化,那么优先对父类初始化,但在<clinit>方法内部不会显示调用父类的<clinit>方法。由JVM负责保证一个类的<clinit>方法执行之前,它的父类<clinit>方法已经被执行。JVM必须确保一个类在初始化的过程中。如果是多线程需要同时初始化它,仅允许其中一个线程对其执行初始化操作,其余线程必须等待,只有在活动线程执行完对类的初始化操作之后,才会通知正在等待的其他线程
准备2.2
元空间/方法区
11
卸载5
重量级锁
getClassLoader
25bit
0 条评论
下一页