Java 面试复习_7

2019-5-30
作者:水不要鱼

(注:能力有限,如有说错,请指正!)

  • JVM 垃圾收集器

如果说垃圾收集算法是接口,那垃圾收集器就是接口的实现了。由于现在 JVM 上一般都会使用分代垃圾回收机制,也就是将堆进一步分为
新生代老年代,根据不同区域的特点进一步选择具体的垃圾回收算法和垃圾回收器,一般来说新生代使用的是复制算法,老年代使用的是
标记清除算法标记整理算法,同理,针对不同的区域也会有不同的垃圾收集器。目前在 JVM 中有以下几种常用的垃圾收集器:

  1. Serial(用于新生代)/ Serial Old(用于老年代)
  2. Parallel Scavenge(用于新生代)/ Parallel Old(用于老年代)
  3. ParNew(用于新生代)
  4. CMS(用于老年代)
  5. G1(新生代和老年代都能用)

不同的业务对于垃圾收集的要求不一样,你可以组合不同的垃圾收集器,比如新生代选择一个,老年代选择另外一个,都可以,但是有些垃圾收集器是不可以一起组合使用的。
不管怎么组合,我们要知道没有完美的垃圾收集器,只有适合的垃圾收集器,所以我们只聊它们的特点,不对比谁好谁坏。

  1. Serial(用于新生代)/ Serial Old(用于老年代)

从名字就能看出来,这是两个单线程的垃圾收集器。其实应该叫一个,因为两个是一样的,只是针对的区域不一样。
这两个垃圾收集器的“单线程”不仅仅是说收集垃圾的时候是单线程,还指整个垃圾收集的过程都是单线程,也就意味在执行垃圾收集的时候,
用户线程是不会执行的,业务就会暂时不可用,这段不可用的时期被称为 STW(Stop The World)。Serial 是针对新生代的,使用复制算法来收集垃圾,
而 Serial Old 是针对老年代的,使用标记整理来收集垃圾。

  1. Parallel Scavenge(用于新生代)/ Parallel Old(用于老年代)

这两个垃圾收集器和 Serial / Serial 很像,只是使用多线程来收集垃圾,而且更多的是关注吞吐量,也就是用户 CPU 时间比值。
上面说过垃圾收集器会存在一个 STW 时间段,就是说在收集垃圾的时候不能执行用户代码,而这两个垃圾收集器虽然是多线程的,但是还是有
STW 这个停顿时间段存在。Parallel Scavenge 是针对新生代的,使用复制算法来收集垃圾,而 Parallel Old 是针对老年代的,
使用标记整理来收集垃圾。

  1. ParNew(用于新生代)

这个垃圾收集器和 Serial / Serial 很像,只是它也是多线程的,和 Parallel Scavenge / Parallel Old 也很像,只是它能和 CMS 垃圾收集器配合使用。
上面说过,ParNew 是针对新生代的,而且不存在 ParNew Old 之类的针对老年代的收集器,所以它可以和 CMS 这个老年代收集器配合使用算是补偿吧。
它使用的垃圾收集算法是复制算法

  1. CMS(用于老年代)

这是个针对老年代的收集器,而且关注点是最短回收停顿时间,也就是说希望 STW 时间尽可能短。它是多线程的,而且和之前的收集器都不一样的是
它使用标记清除算法,这就意味着它收集之后的内存空间是不连续的,如果这时候需要分配一个大对象,可能就需要进行一次整理甚至是执行 Full GC 了。
另外,这个收集器有一个很神奇的地方在于,它允许用户线程同时进行,也就是业务在执行的时候同时执行 GC !这个看起来很神奇,实际上不完全是好事。
首先,业务在执行的时候同时执行 GC 意味着要将 CPU 时间分一部分出来给 GC,如果业务需要的 CPU 资源比较多,就可能导致资源出现争用的问题。
再一个就是,由于在 GC 时程序还在执行,这就有可能还会产生垃圾,这部分新产生的垃圾就被称为浮动垃圾。这就说明这个 GC 没办法针对一整个区域,
如果 GC 清理占用的内存使得程序内存不足,就会启动 Serial Old 来清理了。
这个垃圾收集器有如下几个过程:

  • 初始标记(这个部分存在 STW)
  • 并发标记
  • 重新标记(这个部分存在 STW)
  • 并发清除
  1. G1(新生代和老年代都能用)

这个多线程而且老少通吃(新生代和老年代)的垃圾收集器号称最新高科技收集器,并且打算替换 CMS 收集器。它将整个区域分为多个 Region 区域,
整体使用标记整理算法收集垃圾,而对于两个 Region 是使用复制算法来收集垃圾的,但都是可以整理出完整的连续内存空间的算法。
它分为以下几个阶段:

  • 初始标记(这个部分存在 STW)
  • 并发标记
  • 最终标记(这个部分存在 STW)
  • 筛选回收(这个部分存在 STW)

对象在内存上的分配策略

主要有几个分配策略:

  1. 对象优先在 Eden 区分配

之前说过,对象不一定在堆上,也有可能在栈上分配,这是由于 JIT 编译器使用变量逃逸进行优化导致的情况。
但是绝大多数情况都是在堆上分配,而且优先在 Eden 区进行分配。

  1. 大对象和长期存活的对象直接进入老年代

今晚就到这里,晚安!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值