在java中,当没有对象引用指向原先分配给某个对象 的内存时,该内存便成为垃圾。
什么是垃圾回收?
垃圾回收能自动释放内存空间,减轻编程的负担,JVM的一个系统级线程会自动释放该内存块。垃圾回收意味着程序不再需要的对象是"无用信息",这些信息将被丢弃。当一个对 象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用。
垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存。
引用计数法中,堆里的每个对象实例都有一个引用计数。当一个对象被创建时,且将该对象实例分配给一个变量,该变量计数设置为1。当任何其它变量被赋值为这个对象的引用时,计数加1(a = b,则b引用的对象实例的计数器+1),但当一个对象实例的某个引用超过了生命周期或者被设置为一个新值时,对象实例的引用计数器减1。任何引用计数器为0的对象实例可以被当作垃圾收集。当一个对象实例被垃圾收集时,它引用的任何对象实例的引用计数器减1。
引用计数法的优点:执行快,对程序需要不被长时间打断的实时环境比较有利。
引用计数法的缺点:无法检测出循环引用。当多个对象相互引用时,他们的引用计数永远不为0,但他们本质上是一推垃圾。
通过一系列的‘’GC Roots‘’对象作为起点进行搜索,如果在‘’GC Roots‘’和对象之间没有可达的路径(引用链),则称该对象是不可达的,被判定不可达的对象不一定会成为可回收对象。被判定不可达的对象至少要经历两次标记过程,如果在这两次标记过程中扔没有逃脱成为可回收对象的可能性,则基本就成为可回收的对象了。
GC Roots 对象:虚拟机栈中引用的对象、方法区中类静态属性引用的对象、方法区中常量引用的对象。
分两个阶段:标记阶段:标记出需要被回收的对象。清除阶段:回收被标记的可回收对象的内部空间。
复制算法将可用内存分为两块,每次只用其中一块,当这一块内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已经使用过的内存空间一次性清理掉。
该算法标记阶段和“标志-清除”算法一样,但是在完成标记之后,它不是直接清理可回收对象,而是将存活对象都向一端移动,然后清理掉端边界以外的内存。
将堆区划分为老年代和年轻代,老年代的特点是每次垃圾收集时只有少量对象需要被回收,而年轻代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。
年轻代:所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。
老年代:在年轻代中经历了 N 次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。
持久代:用于存放静态文件。
Serial收集器是最基本,发展最悠久的收集器 ,在jdk1.3之前是虚拟机新生代垃圾回收的唯一选择,它是一个 单线程的收集器,在收集时 其他工作线程会暂停 直到收集结束。
ParNew 收集器是Serial收集器的多线程版本,除了使用多线程进行垃圾回收之外 其余参数和算法好,停止工作线程,回收策略等 与Serial完全一致。
Parallel Scavenge 是一个年轻代收集器,才用复制算法,又是并行的多线程收集器,可以控制吞吐量(cpu运行用户线程的时间与cpu运行总时间比值)
吞吐量=(用户线程工作时间)/(用户线程工作时间+垃圾回收时间)
Serial Old 是Serial收集器的老年代版本,也是单线程 使用标记整理泛
Parallel Old收集器 是Parallel Scavenge的老年代版本,使用多线程标记整理算法,在jdk1.6才开始使用的
CMS 收集器是一种以获取最短停顿时间为目标的收集器,才用的是标记清楚算法,
他的过程分为四个步骤:
只有初始标记 和重新标记需要暂停用户线程
1、初始标记:关联GC Roots能直接关联的对象,速度快
2、并发标记:进行GC RootsTracing的过程
3、重新标记:为了修正并发标记期间,因为用户程序运作导致标记产生变动的那一部分对象。
4、并发清除
缺点:1、cms收集器对cpu资源非常敏感
2、无法处理浮动垃圾
3、因为标记清楚算法,所以会产生大量垃圾碎片。
Jdk1.9以后默认的垃圾收集器
在实际开发中,我们对 new 出来的对象也会根据重要程度,有个等级划分。有些必须用到的对象,我们希望它在其被引用的周期内能一直存在;有些对象可能没那么重要,当内存空间还足够时,可以保留在内存中,如果内存空间在进行垃圾收集后还是非常紧张,则可以抛弃这些对象。
由此,Java 对引用划分为四种:强引用、软引用、弱引用、虚引用,四种引用强度依次减弱。
代码中普遍存在的类似"Object obj = new Object()"这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。
描述有些还有用但并非必需的对象。在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围进行二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。Java 中的类 SoftReference 表示软引用。
描述非必需对象。被弱引用关联的对象只能生存到下一次垃圾回收之前,垃圾收集器工作之后,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。Java 中的类 WeakReference 表示弱引用。
这个引用存在的唯一目的就是在这个对象被收集器回收时收到一个系统通知,被虚引用关联的对象,和其生存时间完全没关系。Java 中的类 PhantomReference 表示虚引用。
原文:https://www.cnblogs.com/kuangliang1/p/14226435.html