JVM脑图
2022-12-21 17:07:11 0 举报
AI智能生成
凌风的技术小屋-JVM脑图
作者其他创作
大纲/内容
局部变量表
操作数栈
动态链接
方法出口
线程栈
本地方法栈
字节码执行行号
程序计数器
编译后代码
类信息
静态变量
常量
Integer== -128 127 问题
运行时常量池
方法区
几乎所有“对象”
数据堆
运行时数据区
DirectByteBuffer
直接内存
内存分布
1.常量池检查类是否加载
整块内存区域划分 【serial、parNew】(新生代)
指针碰撞
碎片化内存,通过指针列表管理【CMS 标记-清除】
空闲列表
2.内存分配
采用CAS同步处理,成功的线程获得对象指针
每个线程在Java堆中分配一小块内存,TLAB用完后,在使用CAS同步-XX:+/-UserTLAB 开关
(Thread Local Allocation Buffer)TLAB
3.对象指针线程并发安全
4.对象头信息设置,类关联,属性值归零
5.<init> 用户构造函数调用
对象创建
MarkWord
实体数据
padding
对象布局
内存分配
优点:简单
缺点:循环引用不可回收
引用计数法
GC Root 根节点开始形成引用连对象到GCRoot没有任何引用链,对象不可达,可以回收
GCRoot:虚拟机栈中本地变量表中的对象:参数、局部变量方法区中静态属性引用的对象方法区中常量引用的对象,常量池中的对象所有被同步锁(synchronized)持有的对象本地方法栈Native方法引用的对象常驻Class对象:异常对象,系统类加载器对象
算法
引用 可达性分析法
没有被访问的对象
白色
已经访问过,并且对象到的所有引用都访问过
黑色
访问过,但至少还有一个引用没访问;全部访问完毕转为黑色
灰色
多标:在扫描过程中黑色断开了引用问题:没有直接影响;可下次 GC再次回收
多标【浮动垃圾】
漏标:原本断开 的白色,在扫描期间被黑色引用了问题:如果白色不变色,就会被清理,被引用的对象反而被回收了
漏标
并发情况
G1、Shenandoah当灰色对象要删除对白色的引用时,就做快照;扫描结束后再次以灰色为根再次扫描一边
原始快照
CMS如果在扫描期间,黑色对象引用了白色的对象,那么就把黑色变灰色结束后再次扫描一边CMS 只能处理 “漏标”,保证对象不丢失,但不能处理浮动垃圾
增量更新
解决方案
并发可达性分析[三色标记]
Object a=new Object()不会被回收
强引用
SoftReference 如果内存不足,就会回收掉;回收后还是不足,就会OutofMemoryError
软引用
weakReference无论内存是否充足,GC时都会回收
弱引用
用于被引用对象 被GC时会产生一个系统通知
虚引用
引用
根节点枚举必须要在JVM 停止运行时进行,类似在一个快照上进行图的搜索
为了降低STW的时间提高枚举效率,HotSpot使用OopMap的数据结构来存放根节点
一旦类加载完毕,就会把对象在什么偏移量上有根节点引用记录;对应线程栈和寄存器里那些位置是引用都会记录
OopMap
引用总是不断在变化的,在每个指令后都生成OopMap 既占用内存,又影响效率JVM在安全点进行OopMap的记录
长时间执行指令的地方:循环方法调用异常调用
安全点的位置
先把所有用户线程中断;如果中断的位置不是安全点,则再次唤醒跑到安全点
抢先式【弃用】
让线程不断去轮询标志位 是否需要中断;如果需要就近找安全点中断
HotSpot 巧妙的使用了一个 内存页不可读的指令:在不需要STW时 某个内存页一直可读;需要时将其设置为不可读既可以让线程暂停挂起,又实现了轮询;
主动通知式
线程如何达到安全点,并停止?
安全点
对于sleep或者blocked的线程不能响应中断信号,怎么办?
安全区域
根节点枚举
当出现夸代引用时,避免把整个老年代加入GCRoots扫描,造成效率底下
字节:具体到某一个内存地址,包含了跨代引用指针
对象:只要对象某一个字段包含跨代引用指针
类似于Map结构;value是一块内存区域,称为卡页卡页中只要有一个对象字段有跨代引用指针,这个页就称为“脏页”
在引用对象赋值时,利用写屏障产生类似AOP的环绕效果,对卡表进行更新每次更新对象引用都会自动更新卡表
通过这个参数开启后,可以避免卡表的“伪共享”缓存行问题每次更新卡表前,先查询表元素,如果没有标记再标记Dirty
-XX:+UseCondCardMark
写屏障“AOP”
如何维护卡表的变化
卡表
卡:某一块内存区域含有某些对象有跨代指针
分类
记忆集和卡表
寻找垃圾 算法
比如常量池中的对象没有任何引用时有可能会被回收
废弃的常量
回收的必要条件:该类的所有实例化对象都都已经回收加载该类的Classloader已经被回收该类的java.lang.Class对象没有任何的引用,无法在任何地方通过反射获取到该类
不再使用的类
回收方法区
弱分代假说:大部分对象 朝生夕灭
强分代假说:熬过越多次GC的对象就越难回收
夸分代解决方案:\"记忆卡\"法在新生代上建立一个全局的记忆卡(Remmbered Set),记录存在跨代引用的老年代内存区域,在Minor GC时,只有包含了跨代引用的小块内存里的对象才会被加入到GCRoots进行扫描
夸分代假说:跨代引用的对象相对于同代引用 数量极少
对象分代假说
优点:简单粗暴,直接将找出需要回收的对象,回收即可
缺点:效率低,如果有大量对象需要回收就会产生大量的标记清除动作容易产生碎片,回收后的内存区域呈现碎片话的状态,不利于分配大内存
代表算法:CMS
标记-清除算法(Mark-Sweep)
将内存分为两块,每次只分配其中一块区域;GC时把存活的对象直接复制到另一块区域;清空已使用区域即可
优点:实现简单,执行效率高,没有内存碎片;适合\"朝生夕灭\"的对象回收
缺点:部分空间不可使用;在Seril ParNew中 Eden和Servivor为 8:1:1也就意味着有1/10的内存不可用
代表算法:新生代的GC算法 Seril和eParNew
标记-复制算法
在标记清除的基础上,将存活的对象移动到内存区域的一侧,形成空闲的一整块内存区域
优点:内存空间碎片少,长时间看有助于系统吞吐量的提高
缺点:整理是一个耗时操作,会增加GC的时长
代表算法:Parallel Scavenge
标记-整理算法(Mark-Compact)
垃圾回收算法
老年代回收器,搭配ParNew新生代使用
标记一下GCRoots根节点能直接关联到的对象
1.初始化标记
从GCRoots为根开始遍历对象图
2.并发标记
由于在并发标记,在标记过程中,和用户线程同时执行,所以会有对象引用变化,存在“多标”和“漏标”现象,需要 三色法的“增量更新” 再次进行标记
3.重新标记
多线程同时回收“白色”的对象
4.并发清除
回收过程
优点:低停顿、高并发
1.对CPU有要求回收时占用1/4的算力;对低于4核的CPU不友好
2.无法处理“浮动垃圾”由于采用了“增量更新”,只能处理“漏标”的情况,对于“多标”的“浮动垃圾”只能等待第二次回收;这样垃圾回收不充分,可能造成老年区内存不够用,进而导致FullGC 的发生
3.会产生内存碎片由于CMS是“标记-清除”垃圾回收器,难免产生内存碎片不过CMS会根据配置,在FUllGC达到一定次数后,进行依次内存整理
缺点
优缺点
CMS (Concurrent Mark Sweep)
G1 (Garbage First)
垃圾回收器
内存回收(GC)
内存
执行引擎
类加载子系统
JVM
0 条评论
回复 删除
下一页