没有合适的资源?快使用搜索试试~ 我知道了~
JVM之问5.0(球友分享).pdf
需积分: 5 0 下载量 124 浏览量
2022-11-30
23:36:06
上传
评论
收藏 3.01MB PDF 举报
温馨提示
试读
30页
JVM之问5.0(球友分享).pdf
资源推荐
资源详情
资源评论
GC篇
堆内分配与回收策略
对象优先在 Eden 区分配
大多数情况下,对象在新生代Eden区中分配,当 Eden区没有足够空间进行分配时,虚拟机将发起
一次 Minor GC
什么是Minor GC
指发生在新生代的垃圾收集,因为 Java对象大多朝生夕灭,所以 Minor GC非常频繁, 一般回收速
度也比较快
大对象直接进入老年代
-XX:PretenureSizeThreshold 当创建的对象超过指定大小时,直接把对象分配在老年代
大对象就是指需要大量连续内存空间的 Java 对象如字符串、数组,为了避免为大对象分配内存时
由于分配担保
机制带来的复制而降低效率
长期存活的对象进入老年代
-XX:MaxTenuringThreshold 设定对象在Survivor区最大年龄阈值,超过阈值转移到老年代,默认
15
对象头的 Age 属性记录年龄,对象在 Eden 出生并经过第一次 Minor GC 后仍然能够存活,并且能
被 Survivor
容纳的话,将被移动到 Survivor 空间中,并将对象年龄设为 1,对象在 Survivor 中每熬过一次
MinorGC,年龄
就增加 1 岁,当它的年龄增加到一定程度(默认为 15 岁),就会被晋升到老年代中
动态对象年龄判定
并不一定要Age到达阈值才晋升到老年代,如果在 Survivor 空间中相同年龄所有对象大小的总和大
于 Survivor 空间的一半, 年龄大于或等于该年龄的对象就可以直接进入老年代
空间分配担保
-XX:HandlePromotionFailure
老年代的连续空间大于新生代对象总大小或者历次晋升到老年代对象的平均大小,就会进行 Minor
GC,否则将进行 Full GC
GC 的分类
部分收集 (Partial GC)
1. 新生代收集(Minor GC / Young GC):只对新生代进行垃圾收集
2. 老年代收集(Major GC / Old GC):只对老年代进行垃圾收集。需要注意的是 Major GC 在
有的语境中也用于指代整堆收集;目前只有 CMS 收集器会有单独收集老年代的行为
3. 混合收集(Mixed GC):对整个新生代和部分老年代进行垃圾收集 目前只有 G1
整堆收集 (Full GC) 收集整个 Java 堆 和 方法区
如何判定对象是否死亡
引用计数法:有地方引用它,计数器加一,引用失效,计数器减一 简单高效但是不能解决循环引
用问题
可达性分析算法:通过一系列的称为 GC Roots 的对象作为起点,从这些节点开始向下搜索,节点
所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话对象不可达,则此对
象不会再被使用
CMS 用增量更新 ,G1用原始快照来进行可达性分析,因为要保证在一致性的快照上进行对象图的遍历
可达性分析算法的优化
可达性分析算法中,从GC Roots集合找引用链时,为了避免从所有 GCRoots 候选位置中进行根节
点枚举,使用OopMap 数据结构来直接得到什么地方存放着对象引用,并不需要真正一个不漏地
从方法区等GC Roots开始查找,缩短了根节点枚举时间
OopMap 存储哪两种对象引用
对象内的引用 在类加载完的时候,HotSpot就把对象内什么偏移量上是什么类型的数据计算
出来
栈、寄存器中引用 在JIT编译过程中,也会在特定的位置记录下栈和寄存器中哪些位置是引用
OopMap 生成条件
只会在安全点生成
什么是安全点
可达性分析算法必须是在一个确保一致性的内存快照中进行。如果在分析的过程中对象引用关系还
在不断变化,分析结果的准确性就不能保证。安全点意味着在这个点时,所有工作线程的状态是确
定的,JVM 就可以安全地执行 GC
安全点选取的条件
能让程序长时间执行的地方,这些指令代表着我们的代码将长时间不会继续往下执行,避免GC等
待太久,就应该在这些地方设立安全点
长时间执行 的最明显特征就是指令序列的复用, 例如方法调用、 循环跳转、 异常跳转等都属于指
令序列复用
如何将线程停止在安全点
抢先式中断 系统中断所有用户线程,没到安全点的,恢复它,让其继续运行到安全点
主动式中断 在安全点设置一个标志,不断轮询这个中断标志,标志为真,就停在安全点指令
安全点存在的 因线程阻塞或休眠,无法响应虚拟机的中断请求,走到安全的地方去中断挂起自己的
问题
什么是安全区
安全点的拓展,是指能够确保在某一段代码片段之中,引用关系不会发生变化,这个区域内,任何
地方垃圾回收都是安全的,解决了上述问题
可达性分析判定为不可达对象一定被回收吗
不一定,如果对象在可达性分析中没有与 GC Root 的引用链,那么此时就会被第一次标记并且进
行一次筛选,筛选的条件是是否有必要执行 finalize() 方法,当对象没有覆盖 finalize() 方法或者已
被虚拟机调用过,那么就认为是没必要的,如果该对象有必要执行 finalize() 方法,那么这个对象
将会放在一个称为 F - Queue 的队列中,虚拟机会触发一个 Finalizer 线程去执行它们的 finalize()
方法 ,此线程是低优先级的,并且虚拟机不会承诺一直等待它运行完,这是因为如果 finalize() 执
行缓慢或者发生了死锁,那么就会造成 F-Queue 队列一直等待,造成了内存回收系统的崩溃。之
后 GC 对处于 F-Queue 中的对象进行第二次被标记,这时,如果对象已经在在 finalize() 中成功拯
救自己 —— 只要重新与引用链上的任何一个对象建立关联即可,如把自己 (this关键字) 赋值给某
个类变量或者对象的成员变量,那在第二次标记时它将被移出 "即将回收" 的集合,如果没有被移
出集合,就会被回收
可达性分析
通过三色标记算法解释 为什么要在一致性的快照上进行对象图的遍历
白色: 对象还未访问,最后还是白色说明对象不可达
黑色: 可达对象 没有引用没扫描过
灰色: 已经被扫描过了但还有引用没扫描过
用户线程与收集线程并行,导致产生浮动垃圾,或则错误回收存活对象 (致命)
1. 插入黑色对象到白色对象引用
2. 删除所有灰色对象到白色对象的直接或间接引用
增量更新用来解决错误回收存活对象
1. 插入的记下来,黑色变灰色 增量更新
2. 删除的也会按没删除搜索 原始快照
什么是 GC Roots
GC Roots 特指的是垃圾收集器(Garbage Collector)的对象,GC会收集那些不是 GC Roots 且没有
被 GC Roots 引用的对象
GC Roots 的对象包括哪几种
虚拟机栈 (栈帧中的局部变量表)中引用的对象、本地方法栈(Native 方法)中引用的对象、方法区中
类静态属性引用的对象、方法区中常量引用的对象 、所有被同步锁持有的对象
四种引用类型
强引用:程序代码中的引用赋值,会持续存在,不会被回收,就算OOM
软引用:软引用是用来描述一些还有用但并非必须的对象,如果内存空间足够,垃圾回收器就不会
回收它,在系统将要发生内存溢出之前,将会把这些对象列入回收范围之中进行第二次回收。如果
这次回收后还没有足够的内存,才会抛出内存溢出异常,用来实现内存敏感的高速缓存; JDK1.2
SoftReference
弱引用:弱引用也是用来描述非必须对象的,他的强度比软引用更弱一些,在垃圾回收时会直接回
收; JDK1.2 WeakReference
虚引用:一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通
知,JVM只管理堆内内存,JDK中直接内存的回收就用到虚引用,JAVA 在申请一块直接内存之后,
会在堆内存分配一个对象保存这个堆外内存的引用,这个对象被垃圾收集器管理,一旦这个对象被
回收,相应的用户线程会收到通知并对直接内存进行清理工作;JDK1.2 PhantomReference
回收方法区
回收常量
字符串常量池中存在字符串 "abc",如果当前没有任何 String 对象引用该字符串常量的话,就
说明常量 "abc" 就是废弃常量,如果这时发生内存回收的话而且有必要的话,"abc" 就会被系
统清理出常量池了
回收类型
该类所有实例都回收;
该类的内加载器也被回收了;
该类对应的Class对象没在任何地方被引用,无法在任何地方通过反射访问该类的方法
垃圾收集算法
分代收集理论
弱分代假说:大部分对象都是朝生夕死
强分代假说:熬过越多次收集也难回收
跨代引假说:占少数(可以通过记忆集,将老年代分成若干块,存在跨代才加入GCRoots中)
记忆集与卡表
局部收集,可能存在跨代引用,记忆集用来记录从非收集区指向收集区存在跨代引用的数据结构,
避免了把整个非收集区(老年代)加入 GCRoots 中,卡表是记忆集的实现
卡表有几种记录精度
字长精度:精确到一个机器字长(就是处理器寻址位数,比如32位或64位)
对象精度:精确到一个对象
卡精度:精确到一块内存区域
在 HotSpot 中一个卡页是多大
一般来讲卡页大小是 2 的 N 次幂
卡表的工作方式
只要卡页内有一个或多个对象的字段存在着跨代指针,那就将对应卡表的数组元素的值标识为1,
称这个元素变脏,在垃圾收集时,只要筛选出卡表中变脏的元素就能得出哪些卡页内存块中包含跨
代指针,把他们加入 GC Roots 中一并扫描
卡表如何更新
通过写屏障
用来更新卡表,G1之前全是写后屏障, 用于引用类型字段赋值时更新卡表。 G1还需要写前屏障来
实现SATB
ZGC 只需要读屏障 (得益于 1.无分代,2.染色指针)
垃圾收集算法
1. 标记 — 清除算法:先标记需清除的对象,之后统一回收。这种方法效率不高,会产生大量不连续
的碎片,且对象越多,效率越低;
2. 标记 — 复制算法:最开始将可用内存按容量划分为大小相等的两块 1:1,每次只使用其中一块。
当使用的这块空间用完了,就将存活对象复制到另一块,再把已使用过的内存空间一次清理掉。优
点是没有空间碎片,简单高效,缺点浪费大量空间;Appel 式 回收将新生代分成 Eden 8:
Survivor 1,Eden 和 一个 Survivor 用于分配,另外 一 Survivor 用于复制,并使用老年代进行分
配担保 - XX:HandlePromotionFailure -XX:SurvivorRatio 8
3. 标记 — 整理算法:先标记存活对象,然后让所有存活对象向一端移动,之后清理端边界以外的内
存;移动回收复杂(更新引用),不移动碎片化分配复杂,总体来说移动的吞吐量最高,CMS(关
注低延迟) 先用标记 - 清除,空间碎片过多,使用标记—整理 -
XX:CMSFullGCsBeforeCompaction CMS收集器执行过若干次不整理空间的 Full GC 之后, 下一
次进入Full GC 前会先进行碎片整理
垃圾收集器
剩余29页未读,继续阅读
资源评论
F1aM1ng0
- 粉丝: 0
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功