一篇帮你搞定JVM中的垃圾回收的基本知识(超级详细)
Posted adventure.Li
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一篇帮你搞定JVM中的垃圾回收的基本知识(超级详细)相关的知识,希望对你有一定的参考价值。
一、总体框架
二、知识介绍
- 如何确定垃圾?
(1)引用计数法
Java中,引用和对象是关联的,操作对象必须用引用进行
。因此,对象如果没有任何与之相关联的引用,即他们的引用数为0,则该对象不太可能用到,即可回收。
(2)可达性分析
为了解决引用计数法存在的循环引用问题(有点类似死锁),Java使用可达性分析的方法。
通过一系列的“GC roots”对象作为起点搜索。如果在 “GC roots”和一个对象之间没有可达路径,则该对象是不可达。另外,不可达对象不等价于回收对象,不可达对象变为可回收对象,需要至少两次标记。
- 主要算法
算法 | 步骤 | 缺 点 |
---|---|---|
标记清除算法(mark-sweep) | 最基础的垃圾回收算法,分为标注 (标记需要回收的对象)和清除 (收回占用的被标记的对象空间,变为未使用的空间)两阶段。 | 内存碎片化验证,后续大对象可能找不到利用空间。 |
复制算法(copying) | 按内存容量将内存划分为等大小的两块。每次只用其中一块,当这块满后将存活对象复制到另外一块 | 将内存压缩到原来的一半。 |
标记整理算法(mark-compact) | 结合以上两种,标记后不是清理对象,而是将存活对象移向内存的另一端 |
- 分代收集算法
是目前大部分JVM所采用的方法。核心思想根据对象的存活的不同生命周期进行内存划分(新生代(新对象频繁创建)和老生代(少量垃圾回收)),然后不同区域选择不同算法进行回收。
新生代:复制算法。
老生代:标记复制算法。
- Java中的四种引用类型
(1)强引用(把对象复制给一个引用变量,这个变量就是强引用)
(2)软引用(SolfReference类来实现)
(3)弱引用
(4)虚引用
- 分区收集算法
将
整个堆区划分为连续的不同小区间
(分代是根据对象的生命周期),每个区间独立使用,独立回收,好处是可以控制一次回收多少个小区间。
- GC垃圾回收器
新生代:Serail、ParNew、Parallel Scavenge.
年老代:CMS、MSC、Parallel Old。
(1)Serial 垃圾回收器 (单线程、复制算法)
最基本的垃圾回收器,使用复制算法,JDK1.3.1之前新生代唯一的垃圾回收器。单线程,没有线程交互的开销,简单而高效。
JVM运行在Client模式
下默认的新生代垃圾回收器。
JVM有两种运行模式Server与Client。两种模式的区别在于,Client模式启动速度较快,Server模式启动较慢;但是启动进入稳定期长期运行之后Server模式的程序运行速度比Client要快很多。这是因为Server模式启动的JVM采用的是重量级的虚拟机,对程序采用了更多的优化;而Client模式启动的JVM采用的是轻量级的虚拟机。所以Server启动慢,但稳定后速度比Client远远要快。参考
(2)ParNew (Serial+多线程)
Serial的多线程版。JVM运行在
Server模式
下默认的新生代垃圾回收器。
(3)Parallel Scavenge (多线程复制算法、高效)
也是新生代的垃圾回收器,他重点关注程序达到一个可控制的吞吐量,主要适用于在后台运行不需要太多交互的任务。自适应调节策略
是Parallel Scavenge与ParNew 的重要区别。
(4)CMS收集器(多线程标记清除算法)
年老代垃圾收集器,主要目标是获取最短垃圾回收停顿时间。采用多线程的标记-清除算法。
(5)G1收集器
目前垃圾回收理论发展最前沿成果,相比较CMS,有以下两优点:
1.基于标记-整理算法,不产生内存碎片
2.可以精准控制停顿时间
以上是关于一篇帮你搞定JVM中的垃圾回收的基本知识(超级详细)的主要内容,如果未能解决你的问题,请参考以下文章
看完这篇总结,你会发现其实spring面试真的没那么难,一篇帮你彻底搞定spring。