第三章-垃圾收集器与内存分配策略
2019-02-27 15:41:00 0 举报
AI智能生成
深入理解Java虚拟机第三章知识归纳
作者其他创作
大纲/内容
关注对象:Java堆和方法区的内存
寻找需要回收的目标
Java堆的回收(对象的死与生)
判断对象的存活
算法
引用计数算法(虚拟机不用这个)
引用计数器=引用此对象的次数
计数器=0 --> 对象不可能再被使用
可达性分析算法
GC Roots作为起始点,向下搜索引用GC Roots的对象
引用链:搜索的路径
GC Roots到这个对象不可达 --> 对象不可用
判断(算法)本质
对象是否存在引用
引用:reference类型的数据中存储的数值代表是另外一块内存的起始地址
强引用
GC永远不会回收被引用对象
软引用
系统发生内存溢出异常之前,将这些对象列进回收范围中进行二次回收
弱引用
只能生存到下一次GC之前
虚引用
唯一目的:在这个对象被收集器回收时收到一个系统通知
临死前的判断
流程图
方法区的回收
废弃常量
类似于判断对象的存活:常量池中的常量是否有被对象引用
无用的类(同时满足三条件)
类的所有实例都被回收,Java堆中没有该类实例
加载该类的ClassLoader已经被回收
类对应的java.lang.Class对象没有在任何地方被引用,无法再任何地方通过反射访问该类的方法
进行回收
垃圾回收算法
标记-清除算法
首先标记需要回收对象,标记完成后统一回收被标记对象
不足:①标记和清除的效率低②清除后会产生大量不连续内存碎片
复制算法
一般复制
将内存分成等大的两块,每次只使用一块,用完一块就将还存活的复制到另一块并清除这一块
代价(过高):将内存缩小为原来的一半
IBM研究复制
过程
①将内存分为一块较大的Eden和两块较小的Survivor空间,每次使用一个Eden一个Survivor
②回收时将两块还活着的对象复制到另一块Survivor,最后清理Eden和刚才用过的Survivor
分配担保机制
如果“复制到另一块Survivor”中的Survivor空间不够,这些对象将直接通过分配担保机制进入老年代(也就是上一次复制的第二块Survivor)
标记-整理算法
标记之后让所有存活的对象都向一端移动,然后直接清理掉边界以外的内存
分代收集算法
根据对象存活周期的不同将内存划分为几块
新生代:每次都有大批对象死,少量活-->复制算法,只需付出少量存活对象的复制成本就可以完成收集
老年代:对象存活率高,没有额外空间对它进行分配担保-->“标记-清理"or“标记-整理”来回收
垃圾收集器(回收的具体实现)
Serial收集器(“单线程”)
①只会使用一个CPU或者一条收集线程去完成垃圾收集
②"Stop the world":垃圾收集时必须暂停所有其他工作线程
ParNew收集器(“单线程”的多线程版本)
使用多条线程进行垃圾收集
Parallel Scavenge收集器(“可控制的吞吐量”)
适合在后台运算不需要太多交互的任务
GC自适应调节策略:动态调整参数来获取最合适提顿时间或最大的吞吐量
停顿时间的缩短:牺牲吞吐量和新生代空间
CMS(Mark Sweep)收集器(“最短停顿时间”)
过程
初始标记("Stop the world")
标记GC Roots能直接关联到的对象
并发标记(耗时最长)
从GC Roots对堆中对象进行可达性分析,找出存活对象
重新标记("Stop the world")
修正在并发标记期间因用户程序仅需运作而导致标记产生变动的那一部分标记记录
并发清除
缺点
占用线程资源-->应用变慢
解决:增量式并发收集器:并发标记、清理时让GC线程、用户线程交替运行
应用并发运行-->浮动垃圾+预留内存空间给用户线程
内存碎片-->内存整理-->停顿
G1收集器
过程
初始标记
标记GC Roots能直接关联到的对象,并且修改TAMS(Next Top at Mark Start)的值
并发标记
最终标记
修正在并发标记期间因用户程序仅需运作而导致标记产生变动的那一部分标记记录
筛选回收
特点
并行与并发
利用多个CPU缩短"Stop the world"时间
分代收集
空间整合
整体上看:基于“标记-整理”算法
局部上(Region之间)看:基于“复制”算法
可预测的停顿
有计划的避免对整个Java堆进行GC,而是将Java堆分成多个等大的独立区域(Region),每次优先回收价值最大的Region
Region的RememberSet
对于引用对象处于不同Region时会记录到被引用对象的Region的RememberSet
防止可达性判断对象存活要扫描整个Java堆
GC Roots(△主要)
△虚拟机栈(栈帧中的本地变量表)中引用的对象
△方法区类静态属性引用的对象
△方法区中常量引用的对象
本地方法栈中JNI(Native方法)引用的对象
HotSpot实现
保证一致性:不可以出现分析过程中对象引用关系还在不断变化
枚举根结点
OopMap数据结构:直接得知哪些地方存放着对象引用
安全点:程序只有执行到安全点时才能暂停去GC
保证所有线程都到安全点才停顿
抢占式中断:首先全部线程中断,有线程中断不在安全点就恢复,让它“跑”到安全点
主动式中断:GC需要中断线程时,不对线程直接操作,通过设置一个flag,让每个线程执行时检查这个flag,flag为真就自己中断挂起
安全区域:安全点的扩展,在此区域内GC都是安全的
内存分配与回收策略
对象优先在Eden分配
没有足够空间的话,虚拟机会发起Minor GC
大对象直接进入老年代
长期存活的对象将进入老年代
出生后经历一个Minor GC到Survivor记为年龄1,此后每经过一次Minor GC年龄+1,直到老年代的年龄阈值就晋升为老年代
动态年龄判定
Survivor空间中相同年龄x所有对象大小和 > Survivor空间一半,此时年龄大于等于x的对象直接进入老年代
空间分配担保
Minor GC安全=老年代最大可用连续空间>新生代所有对象总空间
如果允许担保失败且老年代空间恰好不够:FullGC让老年代腾出更多空间
0 条评论
下一页