前言
什么是垃圾回收?垃圾都会产生在哪?怎么回收?

一、两种回收机制
1.什么是垃圾回收?
垃圾回收就是对内存中已经死亡或者长时间没有使用的对象进行清除和回收。
2.垃圾在哪?
我们都知道Java运行在jvm上,那到底jvm的哪部分的垃圾要通过gc主动回收呢?了解JMM的朋友都知道jdk8之前的方法区和jdk8之后的元数据区的内存分配仅受限于可用的本地内存,在大内存的今天,显然本地内存不会小。所以要被重点关注的垃圾会在线程共享的堆上。
3.怎么回收?
在发生gc时,怎么判断堆中的对象是否是垃圾呢?有两种方法:1.引用计数法。2.可达性分析。
3.1.引用计数法:
给对象添加引用计数器,被引用一次计数器的值就加1;当引用失效时就减1;计数器为0时,对象就是不会再被使用。缺点是无法解决对象之间相互循环引用的问题。
3.2.可达性分析:
这是jvm默认使用的,寻找垃圾算法。是通过一些列称为“GC ROOT”的对象作为起点,从这些节点开始向下搜索,搜索走过的路称为引用链,当一个对象到GC ROOTS没有任何引用链时,就说这个对象是不可达到。

Object D和Object E 、F都是不可达对象,判断为不可用,GC时会被回收,无论Object E和F是否是互相引用,都会被回收。

4.可以作为GC ROOT的对象:
4.1.虚拟机栈中引用的对象。
4.2.方法区中类静态属性引用的对象。
4.3.方法区中常量引用的对象。
4.4.本地方法栈中JNI引用的对象。

GC管理的区域是Java堆,所以选虚拟机栈、方法区和本地方法栈这些不会被GC管理的区域作为GC Root不会被回收。

5.四种引用类型:
强引用 GC Root 可达就不会回收
软引用 SoftReference 灵活控制生存期 空闲内存不足以分配新对象时
弱引用 WeakReference 灵活控制生存期 每次GC
虚引用 PhantomReference 感知对象垃圾回收 每次GC

二、垃圾回收算法
2.1标记 – 清理算法
获取所有GcRoot遍历内存中所有对象,如果可以GCRoot就加个标记,剩下所有的对象都将视为垃圾清除。
优点:实现简单,执行效率高
缺点:容易产生内存碎片
就是垃圾在哪就清理哪,有可能会造成可用内存不连续,存活对象把可用内存分割开。

2.2复制法
将堆分成两个完全相同的区域,对象只在其中一块区域内分配,按顺序将那些存活的对象整体移动到另一块区域,然后回收掉之前那个区域的所有对象。

缺点:虽然解决了碎片化,但是内存减少一半。
2.3标记整理法:
先找到存活对象,然后将它们向空间的一端移动,最后回收到边界以外的垃圾对象

三、垃圾回收策略:
在JVM中垃圾回收器是很繁忙的,如果一个对象存活时间较长,避免重复 创建/回收 给垃圾回收器造成负担,JVM制定了分代回收策略。为每个对象设置生命周期,堆内存划分不同区域,来存储各生命周期的对象,一般情况下Java堆被切分成年轻代、老年代和永久代三部分。

年轻代 主要是用来存放新生的对象,一般占据堆堆1/3空间,保存着大量刚刚创建的对象,大部分都是朝生夕死,所以新生代中会频繁的进行GC
伊利园 年轻代大部分会分配到伊利园代,太大会分配到老年代,当伊利园代内存不够时会出发GC。
幸存者 垃圾回收后还活着的对象

新生代工作流程和复制法较为吻合,都是以复制为核心,所以会采用复制法。
老年代 对象多次回收都没清理掉,被移到老年代。老年代采用了标记清除算法
永久代 永久保存区域,主要存放class和元数据的信息,class在被加载的时候放入永久代

发表评论

邮箱地址不会被公开。