JVM那些事儿,GC(二)

我是方圆,简单入入JVM的门儿

1. GC的作用范围

在这里插入图片描述

2. 四种GC算法

  1. 引用计数算法
    对象创建的时候,就给对象绑定一个计数器。每当有一个引用指向该对象时,计数器加一;每当有引用消除时,计数器减一。在没有引用,即计数器为0时,这个对象被垃圾回收。(JVM的实现不采用这种算法
  • 优点:比较简单;
  • 缺点:无法解决对象循环引用的问题;需要占用额外空间
  1. 复制算法
    该算法应用于两个幸存区中。每次只占用其中一个幸存区,每进行一次MinorGC,将存活下来的对象复制到另一个空的幸存区(to)中,然后之前的幸存区被清空,称为to,而另一个由空变为非空,称为From
  • 优点:不产生内存碎片
  • 缺点:有一部分内存浪费(to区)
  1. 标记清除算法
    在这里插入图片描述
    这个算法分为如下两个阶段,标记阶段:遍历所有的GC Roots,并将所有的存活对象进行标记(这里简单说一下可达性分析算法,只有对象可达的才会被标记);清除阶段:将遍历堆中所有的对象,将没有被标记的对象清除。
  • 优点:相比于引用计数算法,开销更小
  • 缺点:算法复杂度较高,效率比较低;没有移动对象,这种方式清理出的内存不是连续的(碎片化)
  1. 标记整理算法
    标记整理算法是标记清除算法的改进版,适用于老年代的垃圾回收。它们在标记阶段做的工作是相同的,只不过在第二个阶段,该算法并没有直接对死亡的对象进行清理,而是对所有存活的对象进行整理,放到一处存储空间,然后再把剩下的死亡对象全部清除。

标记:从根集合进行扫描,对存活的对象进行标记
清除:移动所有存活的对象,并且按照内存地址次序依次排列,然后将末端内存地址以后的内存全部回收

  • 优点:不产生碎片空间,解决了标记清除算法碎片化的问题
  • 缺点:若存活的对象很多,则效率很低

3. 什么对象会晋升到老年代?

  • 默认情况经历15次Minor GC依然存活的对象
  • Surivor区中存放不下的对象
  • 新生成的对象(-XX:PretenuerSizeThreshold 这个参数可以调节对象大小的阈值,超过这个阈值则会被放在老年代)

4. 常用的调优参数

  • -XX: SurvivorRatio Eden和Survivor的比值,默认8:1
  • -XX:NewRatio 老年代和年轻代内存大小的比值,默认2:1
  • -XX:MaxTenuringThreshold 对象从年轻代晋升到老年代,经过的GC次数的阈值
  • -XX:+PretenuerSizeThreshold 大对象直接放入老年代文件大小的阈值

5. 触发Full GC的条件

  1. 老年代空间不足
  2. 调用System.gc();
  3. 永久代空间不足(JDK1.7及之前)
  4. CMS GC时出现 promotion failed,concurrent mode failure
  5. Minor GC 晋升到老年代的平均大小大于老年代剩余空间
  6. 使用RMI来进行RPC或管理的JDK应用,每小时执行1次Full GC

6. Stop-the-world 和 Safepoint

  1. Stop-the-world

JVM进行任何GC都会停止应用程序的执行,多数GC的优化就是减少了Stop-the-world来提高性能

  1. Safepoint

安全点是对象引用关系不会发生变化的点,产生安全点的地方,方法调用;循环跳转;异常跳转等,线程停顿就需要停在安全点处

7. JVM的运行模式

  1. Server:启动慢,运行快(重量级虚拟机)
  2. Client:启动快,运行慢(轻量级虚拟机,可用java -version命令查看)

8. 常见的垃圾收集器

在这里插入图片描述

8.1 年轻代常见的垃圾收集器

  1. Serial收集器(-XX:+UseSerialGC,复制算法)
    单线程垃圾收集,必须暂停所有的工作线程
    简单高效,Client模式下默认使用的年轻代收集器
  2. ParNew收集器(-XX:+UseParNewGC,复制算法)
    多线程收集,其余的行为和Serial收集器一样
    单核执行效率不如Serial收集器,在多核下优势明显
  3. Parallel Scavenge收集器(-XX:+UseParallelGC,复制算法)
    更关注吞吐量,适合用于后台服务,更好的利用CPU,而不适合用于交互(吞吐量=执行代码的时间/(执行代码的时间 + 垃圾回收的时间)
    在多核情况下优势明显,是Server默认使用的年轻代收集器

8.2 老年代常见的垃圾收集器

  1. Serial Old收集器(-XX:+UseSerialOldGC,标记-整理算法)
    单线程垃圾收集,必须暂停所有的工作线程
    简单高效,Client模式下默认老年代收集器
  2. Parallel Old收集器(-XX:+UseParallelOldGC,标记-整理算法)
    多线程下,吞吐量优先
  3. CMS收集器(-XX:+UseConcMarkSweepGC,标记-清除算法)
    很屌的收集器,几乎能与工作线程同时进行,减少了Stop-the-world的时间

8.3 年轻代和老年代都能用的收集器

  • GarbageFirst收集器(-XX:+UseG1GC,复制算法+标记整理算法)
  • 特点:并行和并发;分代收集;可预测的停顿;空间整合
  • 工作方式:将整个Java堆内存划分成多个大小相同的Region,年轻代和老年代不再物理隔离

在这里插入图片描述

同系列

JVM那些事儿,这些必会的知识点(一)

参考文献

JVM的四种GC算法

扫描二维码关注公众号,回复: 11217544 查看本文章

JVM:GC(垃圾回收算法)

原创文章 56 获赞 19 访问量 6014

猜你喜欢

转载自blog.csdn.net/qq_46225886/article/details/106084634