JVM GC只回收堆区和方法区内的对象。而栈区的数据,在超出作用域后会被JVM自动释放掉,所以其不在JVM GC的管理范围内。
GC的主要区域是堆,堆里包含两大块区域,新生代(Young)和老年代(Old)。
默认的新生代(Young generation)、老年代(Old generation)所占空间比例为 1 : 2
Young中包含三块区域,Eden、suvivor1、suvivor2。三块区域默认的空间比8:1:1。下面着重讲解GC的工作过程
注意:永久代(方法区)在jdk8之前也会很容易触发FullGC。方法区存放着类的信息。当系统中加载的类或者反射的类太多的时候,永久代内存会不足。
新生代GC用到的算法是复制算法,老年代是标记-整理算法。
在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用技术器得值就+1,当引用失效的时候,计数器得值就-1
算法缺点:当某个引用被收集时,下个引用并不会清0,因此不被回收造成内存泄露。
GCroot结点开始向下搜索,路径称为引用链,当对象没有任何一条引用链链接的时候,就认为这个对象是垃圾,并进行回收。
那么什么是GCroot呢(虚拟机在哪查找GCroot)。
目前主流JVM采用的垃圾判定算法就是可达性分析法。
将确定为垃圾的对象进行标记,然后统一回收。
如图所示:黄色的就是被标记清除的。清除后会发现有很多多余的小块。
存在的问题: 1.效率问题 2.内存小块过多。
2.复制算法
将内存区域划分成两块,每次回收时,将依然存活的对象从一块复制到另一块,然后清除不在存活的对象。这样就完成了内存的连续分配,但是引来一个问题。
每次只能使用一半的内存。是不是有点少。。
为了解决这个问题,我们对内存就进行了划分。
我们对内存分为了三块区域。
复制算法主要针对新生代内存收集方法。
标记-整理算法主要针对的是老年代内存收集方法
然后将右面的进行删除就达到回收效果
标记 - 清除算法: 存在效率问题 & 内存碎片问题
复制算法: 将内存划分为两块大小相等的区域,回收时,把存活的对象复制到另外一块
高效 but 内存缩小了一半
采用此算法回收新生代,一块较大的Eden区和两块较小的Survivor区: 将Eden和Survivor活着的对象一次性复制到另外一个Survivor区
HotSpot默认Eden和Survivor大小8:1
Survivor不够用时 需要老年代空间进行内存分配担保
标记 - 整理算法: 标记后不对可回收对象进行清除,而是让活着的对象向一段移动,然后直接清理掉边界以外的内存
单线程,进行GC时,必须暂停其他工作线程,直到GC结束 Client模式下默认的新生代收集器
2. ParNew(新生代)
Serial的多线程版 Server模式下默认的新生代收集器(与CMS收集器配合)
3. Parallel Scavenge(新生代)
目标是达到一个可控制的吞吐量 可开启GC自适应的调节策略 复制算法 & 多线程
4. Serial Old(老年代)
Serail的老年代版本 标记 - 整理
5. Paraller Old(老年代)
Parallel Scavenge的老年代版本 多线程 & 标记 - 整理
6. CMS(老年代)
7. G1(老年代)
配合使用图:
相关参数:
注:
parallel Scavenge适合后台任务处理,侧重吞吐量,处理更多任务
CMS:低延迟,高响应
CMS 跟 Serial 侧重于低暂停时间 适合实时响应服务.
CMS缺点:吞吐量低
原文:https://www.cnblogs.com/shengedong/p/12531240.html