1. 自动垃圾收集
-
自动垃圾收集是查看堆内存,识别正在使用哪些对象以及哪些对象未被使用以及删除未使用对象的过程。
-
使用中的对象或引用的对象意味着程序的某些部分仍然维护指向该对象的指针。
-
程序的任何部分都不再使用的对象或未引用的对象,可以回收未引用对象使用的内存。
2. 如何确定内存需要被回收
- 该过程的第一步称为标记。这是垃圾收集器识别哪些内存正在使用而哪些不再使用的地方。
-
不同类型内存的判断方式
- 对象回收-引用计数
- 对象回收-可达性分析
- 方法区回收
可达性分析算法
- 简单来说,将对象及其引用关系看作一个图,选定活动的对象作为 GC Roots;
- 然后跟踪引用链条,如果一个对象和 GC Roots 之间不可达,也就是不存在引用,那么即可认为是可回收对象。
引用类型和可达性级别
-
引用类型
- 强引用(StrongReference):最常见的普通对象引用,只要还有一个强引用指向一个对象,就不会回收。
- 软引用(SoftReference):JVM 认为内存不足时,才会去试图回收软引用指向的对象(缓存场景)。
- 弱引用(WeakReference):虽然是引用,但随时可能被回收掉。
- 虚引用(PhantomReference):不能通过它访问对象。用于对象被 finalize 以后,执行指定逻辑的机制(Cleaner)。
-
可达性级别
- 强可达(Strongly Reachable):一个对象可以有一个或者多个线程可以不通过各种引用访问到的情况。
- 软可达(Softly Reachable):就是当我们只能通过软引用才能访问到对象的状态。
- 弱可达(Weakly Reachable):只能通过弱引用访问时的状态。当弱引用被清除的时候,就符合销毁条件。
- 幻象可达(Phantom Reachable):不存在其他引用,并且 finalize 过了,只有幻象引用指向这个对象。
- 不可达(unreachable):意味着对象可以被清除了。
3. 垃圾收集算法
标记-清除(Mark-Sweep)算法
- 首先识别出所有要回收的对象,然后进行清除。
- 标记、清除过程效率有限,有内存碎片化问题,不适合特别大的堆。
- 收集算法基本基于标记-清除的思路改进。
复制(Copying)算法
- 划分两块同等大小的区域,收集时将活着的对象复制到另一块区域。
- 拷贝过程中将对象顺序放置,就可以避免内存碎片化。
- 复制+预留内存,有一定的浪费。
标记-整理(Mark-Compact)算法
- 类似于标记-清除,但为避免内存碎片化,它会在清理过程中将对象移动,以确保移动后的对象占用连续的内存空间。
4. 分代收集
- 根据对象的存活周期,将内存划分为几个区域,不同区域采用合适的垃圾收集算法。
- 新对象会分配到 Eden,如果超过 -XX:+PretenureSizeThreshold:设置大对象直接进入老年代的阀值。
新生代(复制算法)
老年代(标记-整理)
5. 垃圾收集器
串行收集器
-
Serial GC -XX:+UseSerialGC
- 单个线程来执行所有垃圾收集工作,适合单处理器机器。
- Client 模式下 JVM 的默认选项。
-
Serial Old -XX:+UseSerialOldGC
- 可以在老年代使用,它采用了标记-整理(Mark-Compact)算法,区别于新生代的复制算法。
并行收集器1
-
Parallel GC -XX:+UseParallelGC、Parallel Old GC -XX:+UseParallelOldGC
-
server 模式 JVM 的默认 GC 选择,整体算法和 Serial 比较相似,区别是新生代和老年代 GC 都是并行进行的。
-
可以设置 GC 时间或吞吐量等值,可以自动进行适应性调整 Eden、Survivor 大小和 MaxTenuringThreshold 的值。
-
也称为吞吐量优先的 GC:吞吐量=用户代码运行时间/(用户代码运行时间+GC时间)
-
参数设置
- -XX:ParallelGCThreads:设置用于垃圾回收的线程数。通常情况下可以与 CPU 数量相等。
- -XX:MaxGCPauseMills:设置最大垃圾收集停顿时间。它的值是一个大于 0 的整数。
- -XX:GCTimeRatio:设置吞吐量大小,它的值是一个 0-100 之间的整数。
- -XX:UseAdaptiveSizePolicy:打开自适应 GC 策略。以达到在堆大小、吞吐量和停顿时间之间的平衡点。
并发收集器1
-
CMS(Concurrent Mark Sweep)GC -XX:+UseConcMarkSweepGC
-
专用老年代,基于标记-清除(Mark-Sweep)算法,设计目标是尽量减少停顿时间。
-
采用的标记-清除算法,存在着内存碎片化问题,长时间运行等情况下发生 full GC,导致恶劣的停顿。
-
CMS 会占用更多 CPU 资源,并和用户线程争抢。
并行收集器2
-
ParNew GC -XX:+UseParNewGC
-
新生代 GC 实现,它实际时 Serial GC 的多线程版本。
-
可以控制线程数量,参数 -XX:ParallelGCThreads
-
最常见的场景是配合老年代 CMS GC 工作。参数 -XX:+UseConcMarkSweepGC
并发收集器2
-
G1 -XX:+UseG1GC
-
针对大堆内存设计的收集器,兼顾吞吐量和停顿时间,JDK9 后为默认选型,目标是替代 CMS。
-
G1 将堆分成固定大小的区域,Region 之间时复制算法,但整体上可看作是标记-整理(Mark-Compact)算法,可以有效地避免内存碎片。
-
红色新生代(Eden 和 Surivor),淡蓝色老年代。找不到大内存时执行 FullGC。
6. 垃圾收集器组合
来源:oschina
链接:https://my.oschina.net/shadowolf/blog/4275236