JVM之 GC(垃圾回收)

当进程启动后会创建垃圾回收线程,来回收内存中无用的对象
1.垃圾回收的时机
(1)System.gc()
显示的调用此方法, 建议JVM进行fgc(full gc),虽然只是建议而非一定,但多半都会进行fgc, 增加fgc的频率,所以一般不用此方法,而是让JVM自己管理它的内存

(2)jvm 垃圾回收机制决定
创建对象需要分配内存, 当内存不足时 出发GC;
finalize(),java.lang.Object中的方法,当JVM发现不在有引用指向某对象时,垃圾收集器会在对象上调用该方法
2.垃圾回收策略—如何判断对象可回收
2.1引用计数算法
给对象添加一个引用计数器,当有引用指向该对象时,计数器加1 ,当引用失效时,计数器值减一, 当值为0时,说明没有引用指向该对象. 该算法实现简单,效率高,但它很难解决对象之间循环引用的问题

2.2可达性算法
把一系列称为GC Roots的对象作为起始点,从这些起始点向下搜索,搜索走过的路径称为GC Roots引用链,当对象到GC Roots 没有任何引用链相连(从GC Roots到这个对象不可达)时,说明该对象是不可用的。
如下图,object5 和object6 到GC Roots是不可达的,因此被判定为可回收对象
在这里插入图片描述
3.需要垃圾回收的内存划分
3.1方法区(JDK1.7)或元空间(JDK1.8)
JDK1.7的方法区在GC中被称为永久代
JDK1.8的元空间在本地内存中,GC也是对元空间的垃圾回收
主要回收废弃的常量和无用的类, 此区域GC的"性价比"很低
3.2堆
java堆是垃圾收集器主要管理区域,也被称为"GC堆";
由于垃圾收集器 分代 采用不同的收集算法, 所以 java堆可细分为:
在这里插入图片描述
(1)新生代(Young Generation) 又可分为Eden ,from surviver ,to surviver
发生在新生代的GC 称为young GC(YGC) 或Minor GC ,因为java对象大多具备朝生夕灭的特性,所以manor GC发生的很频繁,而且回收速度很快.
(2)老年代(old Generation) 发生在老年代的GC被称为Major GC.出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对的,在Parallel Scavenge收集器的收集策略里就有直接进行Major GC的策略选择过程)。Major GC的回收速度比Manor GC的速度要慢10倍左右.
(3)Full GC 在不同的语义中,定义也不同,可以是老年代GC,可以是全堆(老年代+新生代),也可以指用户线程暂停(stop-the-world)的垃圾回收.

4.垃圾回收算法
4.1标记–清除算法(Mark Sweep)
老年代收集算法.
分为标记和 清除 两个阶段,先把所有回收对象标记上,在统一清理,
不足:①效率不高,② 会产生大量不连续的内存碎片,导致后续为大对象分配内存时,没有足够的连续的内存,就会提前触发垃圾收集动作
4.2标记–整理算法(Mark Compact)
老年代收集算法
和"标记–清除算法"过程一致,但清除阶段不是直接清除,而是把存活对象移动到一端,然后清除掉边界以外的内存
4.3复制算法(Copying)
新生代收集算法
把内存按容量分为两块大小相等的区域, 每次只用一块儿,当这一块要用完了就把所有存活对象复制到另一块上去,然后把这一块儿全部清理掉.
实现简单,效率高
不足:内存利用率太低了

5.垃圾回收过程
当eden空间不足时,会触发Manor GC:(对象优先在Eden上分配),把Eden和用过得Surviver中存活的对象复制到另一块Surviver上,然后把Eden和之前那块Surviver清理掉
在这里插入图片描述
年老对象进入到老年代: JVM给对象定义一个对象年龄计数器,当对象经过一次Manor GC后仍然存活,那么年龄加一,当增加到一定值后(默认15),就进入到老年代.
当surviver内存不足时,通过分配担保机制,存活对象进入到老年代.

6.垃圾收集的影响

6.1用户线程暂停–stop-the-world (STW)
垃圾回收工作要在垃圾回收线程里进行,所以,多数时候,当进行垃圾回收时,或进行期中一步骤时,会暂停用户线程.
垃圾回收需要先标记,在标记对象时,用户线程并发执行时,可能把已标记的对象重新加入引用链,此时,再回收这个对象就会产生问题.

所以用户线程会在特定安全点停下来开始GC;
抢先试中断:不需要线程的代码主动配合,而是在发生GC时把所有线程中断,若不在安全点,就恢复线程,让它跑到安全点.(此方法用的极少)
主动式中断:在执行GC时,会设置一个标志,线程主动去轮询这个标志,当中断标志为真时就自己中断挂起, 轮询标志的地方和安全点是重合的.
6.2评价垃圾回收器的指标----吞吐量和停顿时间(用户体验)
吞吐量:CPU用于运行用户代码的时间 除以 CPU总的运行时间 , 即吞吐量=运行用户代码时间/
(运行用户代码时间+垃圾收集时间)
单次停顿时间与总的停顿时间一般是反比
用户体验优先:用户线程单次停顿时间短,即使总的停顿时间长一点也可以接受。
吞吐量优先:用户线程总的停顿时间短,即使单次停顿时间长一点也可以接受。

7.垃圾收集器
在这里插入图片描述
1.CMS收集器(老年代收集器,并发GC)
特性:
并发收集、低停顿
“标记-清除”算法
整个过程分为4个步骤:

  1. 初始标记(CMS initial mark) 初始标记仅仅只是标记一下GC Roots能直接关联到的对象,
    速度很快, 需要“Stop The World”。
  2. 并发标记(CMS concurrent mark) 并发标记阶段就是进行GC Roots Tracing的过程。
  3. 重新标记(CMS remark) 重新标记阶段是为了修正并发标记期间因用户程序继续运作而导
    致标记产生 变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍
    长一些,但远比并发标 记的时间短,仍然需要“Stop The World”。
  4. 并发清除(CMS concurrent sweep) 并发清除阶段会清除对象。
    缺陷:
    ①抢占CPU资源
    ②无法处理浮动垃圾:由于并发清理过程,用户线程也在执行,所以会产生对象和垃圾, 而产生的垃圾没有标记 ,需要累积到下一次CMS集中处理,所以,需要预留一部分空间给并发执行的程序. 如果在清除阶段,内存不足,就会临时调用单线程的Serial Old收集器来重新进行老年代的垃圾收集,这样的话,CMS原本降低停顿时间的目的不仅没完成,和直接使用Serial Old收集器相比,还增加了前面几个阶段的停顿时间。
    ③会产生不连续的空间碎片—由"标记-清除"的算法决定.

2 .G1收集器
用户体验优先
把heap区分为很多region块.然后并行对其垃圾回收
无论如何,G1收集器采用的算法都意味着 一个region有可能属于Eden,Survivor或者Tenured
内存区域。
在这里插入图片描述
年轻代垃圾收集
在G1垃圾收集器中,年轻代的垃圾回收过程使用复制算法。把Eden区和Survivor区的对象复制到新的
Survivor区域。

老年代垃收集
对于老年代上的垃圾收集,G1垃圾收集器也分为4个阶段,基本跟CMS垃圾收集器一样,但略有不同:
初始标记:需要暂停用户线程,同Manor GC一起执行,
并发标记: 发现哪些Tenured region中对象的存活率很小或者基本没有对象存活,那么G1就会在这个阶段将其回收掉,而不用等到后面的清除阶段.
最终标记(CMS中的Remark阶段) - 在这个阶段G1做的事情跟CMS一样, 但是采用的算法不
同,G1采用一种叫做SATB(snapshot-at-the-begining)的算法能够在Remark阶段更快的标
记可达对象。
筛选回收(Clean up/Copy)阶段 - 在G1中,没有CMS中对应的Sweep阶段。相反 它有一个
Clean up/Copy阶段,在这个阶段中,G1会挑选出那些对象存活率低的region进行回收,这个
阶段也是和minor gc一同发生的,如下图所示:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值