垃圾回收算法和垃圾收集器(4)

一、概述

问题:

  • 垃圾回收回收什么(what)
  • 垃圾什么时候回收(when)
  • 怎么回收(how)

回收什么

我们java内存中有:java堆,java栈,方法区,直接内存
其中java栈是跟随线程生命周期的,所以不需要我们回收。
我们主要的回收目标:java堆、方法区、直接内存
方法区主要回收类和常量

什么时候回收

当对象没有引用的时候:
1、引用计数法:当对象被引用时,计数+1,当计数为0时,可被回收
缺点:会出现循环引用的情况,导致多个对象一直不能回收,比如python
2、可达性分析法:根据gcroot节点,分析一个对象是否可达,若不可达,则可以回收
GC root:java虚拟机栈、java本地方法栈、方法区中的类静态变量、方法区中的类常量对象
有引用:java中有4中引用关系

  • 强引用:Object obj = new Object();不会被回收
  • 软应用:softReference,当java将要发生内存溢出之前,会被回收
  • 弱引用:WeakReference 下次执行垃圾回收时,会被回收
  • 虚引用:PhantormReference 和没有引用一样,只不过当回收时,会给对象一个finalize()的通知

二、垃圾回收算法

  • 标记清除法
  • 复制法
  • 标记整理法
  • 分区法
  • 分代法

标记清除法

标记哪些可被回收,然后直接清除
缺点:标记和清除效率低、产生碎片化的内存

复制法

把内存分为2个相同大小的区域,一次只用一个,把存活的对象复制到内外一个内存空间,然后清除所有的对象
优点:没有内存碎片,如果存活率低的话提高效率
缺点:如果存活的对象多,效率低
适合于存活率低的年轻代的算法

标记整理法

先标记存活的对象,然后移动到一边,再清除剩余的内存
优点:减少碎片化
适用于大多数对象长时间没有被回收的情况,老年代

分代法

上面2个的综合,根据不同对象的特征分为年轻代和老年代
年轻代分为:eden、Survivor from和Survivor to。默认8:1

分区法

把内存分为很多相同大小的区。G1中使用。可单独对其中部分区进行内存回收。减少stw时间,提升效率。

三、垃圾回收器

  • serial new
  • parnew
  • parallel scavenge
  • serial old
  • parallel old
  • CMS
  • G1

serial new单线程回收器

年轻代的单线程回收器,使用的复制算法,垃圾回收时是单线程执行的
年轻代client的默认回收器

parnew多线程回收器

和serial相比,回收时是多线程的,使用的复制算法
年轻代server的默认回收器
组合:parnew+CMS配合使用

parallel scavenge

和parnew类似,使用复制算法,只不过parallel scavenge跟关注吞吐量,更适用于计算型的后台程序;而其他回收器更关注stw的时间;更适用于响应的服务
组合:parallel scavenge+ parallel old 更关注吞吐量

serial old单线程回收器

老年代的单线程回收器,使用的标记整理算法,垃圾回收时是单线程执行的
老年代client的默认回收器

parallel old多线程回收器

和serial相比,回收时是多线程的,使用的标记整理算法

CMS回收器

老年代的回收器,更强调stw时间。
过程
- 初始标记:标记GC root
- 并发标记:标记存活对象
- 再次标记:把这个过程中有变动的标记下
- 并发清除
其中只有初始标记和再次标记是stw的,其他都是和用户线程并行的,stw时间很短
问题:
1、并发占用正常线程,cpu吞吐量下降
2、并发标记需要额为占用内存,不能等内存满了再开始回收,如果设置阈值过高,可能发生fail的请求,引发fullgc。使用parallel old兜底。
3、没有整理产生碎片,可以设置每次回收整理一次,或者N次回收整理一次内存对象

G1回收器

jdk1.7引入,适用于年轻代和老年代,引入分区概念,初始标记-并发标记-最终标记-筛选回收。可以一次只回收一个或几个有价值的区。减少stw时间。

三、什么时候执行垃圾回收

YGC:
1、当eden满了的时候
FULL GC:
1、system.gc() 不一定立马回收
2、当老年代快满了的时候
3、方法区快满了的时候
4、通过Minor GC后进入老年代的平均大小大于老年代的可用内存
5、当某次Minor GC后进入老年代的大小大于老年代的可用内存时

四、什么时候进入老年代

1、eden和from的存活对象放不下to的时候,部分对象进入老年代
2、当分配一个大对象的时候,直接进入老年代。字符串、字符数组等,可设置
3、当年轻代的对象年龄太大的,进入老年代。默认是15,一次回收+1;或者年轻代同年龄的对象占比大于50%时

五:其他

Oopmap:存储GCroot,方便查询gc root对象
安全点、安全区:当这段程序执行时没有对象的变动时,被编辑为安全点/区。才能执行垃圾回收动作。

六:一些参数设置

这里写图片描述

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值