3. JVM GC算法及具体垃圾收集器

3. JVM GC算法及具体垃圾收集器 3.1 基础目标
GC和内存分配的作用
当需要排查各种内存溢出、内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就必须对这些“自动化”的技术实施必要的监控和调节 。
什么内存需要回收?
3.2 对象已死?
从上面的什么内存许要回收中我们知道许要回收的对象大部分存在堆/方法区中,此时还要解决一个找到可被回收对象的问题,否则一个对象正在使用就被内存回收了 程序允许会走向不可预知的错误 。
判断对象已死的方法
可达性分析3.2.1再谈引用
Java引用分类
软引用(Soft )
弱引用(Weak )
虚引用( )
3.2.2回收方法区
方法区的垃圾收集主要回收两部分内容:废弃的常量和不再使用的类型 。
常量只要没有被引用就能被回收
类对象则需要
没有实例化的对象没有类加载器没有被反射 3.3垃圾收集算法 3.3.1分代收集理论
当前大多数垃圾收集器都遵循分代收集( ),垃圾收集建立在分代收集理论之上,分代收集理论指导了如何高效回收垃圾
分代收集建立在一些假说之上
弱分代假说(Weak)
绝大多数对象都是朝生夕灭的
强分代假说()
熬过越多次垃圾收集过程的对象就越难消亡
跨代收集假说()
跨代对象相对来说是少数,并且最后会到同一分代中消除跨代(例如新生代被老年代依赖,新生代对象就会熬过一次次GC最终进入老年代消除跨代)
分代收集假说推出了对象要分代存放,并且根据不同区域使用不同的收集算法
JVM中一般将Java堆划分为两部分
新生代(young )老年代(old )
分代收集理论引出一个问题:对象不是孤立的,会存在跨代引用
减少新生代对象跨代引用扫描整个老年代的解决方案记忆集( Set)
将老年代划分为若干个小块标识出老年代的哪一块内存会存在跨代引用,发生Minor GC只扫描这一块
GC定义
整堆收集(Full GC)
以下GC图片来源
3.3.2 标记-清除算法
问题3.3.3标记-复制算法
带整理的GC算法
解决标记清除算法随着要回收对象增加导致效率降低的问题,通过内存块复制到另一区域(并整理)来保证清理的效率以及内存的连续
// 新生代收集器都使用这种算法
问题
内存浪费
解决
通过8:1:1将新生代划分为Eden+两个区域来避免内存浪费,因为新生代的特性每次回收大量内存,所以存货的对象占用内存不会很多,若超过限制则直接进入老年代
3.3.4标记-整理算法
标记-复制与标记-清除算法一致,但最后回收是将所有对象移动到内存一端,然后清理掉边界以外的所有对象 。
老年代算法,但移动对象与更新引用需要STW,避免运行对对象移动与清理造成影响
注重吞吐量,CMS注重延迟
CMS是老年代垃圾收集器,采用标记-清理算法,在内存碎片太多后采用标记-整理算法
3.4 的算法细节 3.4.1 根节点枚举3.4.2 安全点
使用会随着程序运行导致map变更,每条指令都要维护map成本太高
安全点就是更新的时间点,这个时间点不能太多也不能太少,太多影响性能太少影响准确性 。
安全点选在程序长时间执行之前 。
程序中断分为两种
抢先式
对程序运行不友好
主动式
设定标识位让线程沦陷然后主动中断
3.3.3 安全区域

3. JVM GC算法及具体垃圾收集器

文章插图
在一段时间内对象关系不变的点,可理解为安全点的集合