一、垃圾回收算法
程序的运行必然需要申请内存资源,无效的对象资源如果不及时处理就会一直占有内存资源,最终将导致内存溢出,所以对内存资源的管理是非常重要了。常见的垃圾回收算法有:引用计数法、标记清除法、标记压缩法、复制算法、分代算法。
1、引用计数法
原理:
假设有一个对象A,任何一个对象对A的引用,那么对象A的引用计数器+1,当引用失败时,对象A的引用计数器就-1,如果对象A的计数器的值为0,就说明对象A没有引用了,可以被回收。
优点:
实时性较高,无需等到内存不够的时候,才开始回收,运行时根据对象的计数器是否为0,就可以直接回收。在垃圾回收过程中,应用无需挂起。如果申请内存时,内存不足,则立刻报outofmember错误。区域性,更新对象的计数器时,只是影响到该对象,不会扫描全部对象。
缺点:
每次对象被引用时,都需要去更新计数器,有一点时间开销。
浪费CPU资源,即使内存够用,仍然在运行时进行计数器的统计。
无法解决循环引用问题。(最大的缺点)
2、标记清除法
标记:从根节点开始标记引用的对象。
清除:未被标记引用的对象就是垃圾对象,可以被清理。
优缺点:
可以看到,标记清除算法解决了引用计数算法中的循环引用的问题,没有从root节点引
用的对象都会被回收。同样,标记清除算法也是有缺点的:
效率较低,在GC时,需要停止应用程序,对于交互性要求比较高的应用而言这个体验是非常差的。
碎片化较为严重,因为被回收的对象可能存在于内存的各个角落,所以清理出来的内存是不连贯的。
2、标记压缩法
标记压缩算法是在标记清除算法的基础之上,做了优化改进的算法。在清理阶段,并不是简单的清理未标记的对象,而是将存活的对象压缩到内存的一端,然后清理边界以外的垃圾,从而解决了碎片化的问题。
优缺点
优缺点同标记清除算法,解决了标记清除算法的碎片化的问题,同时,标记压缩算法多了一步,对象移动内存位置的步骤,其效率也有有一定的影响。
4、复制算法(新生代使用该算法)
复制算法的核心就是,将原有的内存空间一分为二,每次只用其中的一块,在垃圾回收时,将正在使用的对象复制到另一个内存空间中,然后将该内存空间清空,交换两个内存的角色,完成垃圾的回收。如果内存中的垃圾对象较多,需要复制的对象就较少,这种情况下适合使用该方式,并且效率比较高,反之,则不适合。
优点:
在垃圾对象多的情况下,效率较高。清理后,内存无碎片。
缺点:
在垃圾对象少的情况下,不适用,如:老年代内存。
分配的2块内存空间,在同一个时刻,只能使用一半,内存使用率较低。
5、分代算法
前面介绍了多种回收算法,每一种算法都有自己的优点也有缺点,谁都不能替代谁,所以根据垃圾回收对象的特点进行选择,才是明智的选择。
分代算法其实就是这样的,根据回收对象的特点进行选择,在jvm中,年轻代适合使用复制算法,老年代适合使用标记清除或标记压缩算法。
二、垃圾收集器
包括:串行垃圾收集器、并行垃圾收集器、CMS(并发)垃圾收集器、G1垃圾收集器。
jdk1.7 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)
jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)
jdk1.9 默认垃圾收集器G1
java -XX:+PrintCommandLineFlags -version参数可查看默认设置收集器类型,ParallelGC表示的是 Parallel Scavenge(新生代)+ Parallel Old(老年代)。在实践中使用UseConcMarkSweepGC 表示 “ParNew” + “CMS” 的组合是经常使用的
-XX:+PrintGCDetails亦可通过打印的GC日志的新生代、老年代名称判断
1、串行垃圾收集器(DefNew)
是指使用单线程进行垃圾回收,垃圾回收时,只有一个线程在工作,并且java应用中的所有线程都要暂停,等待垃圾回收的完成。这种现象称之为STW(Stop-The-World)。对于交互性较强的应用而言,这种垃圾收集器是不能够接受的。一般在Javaweb应用中是不会采用该收集器的。
2、并行垃圾收集器(ParNew和ParallelGC)
并行垃圾收集器在串行垃圾收集器的基础之上做了改进,将单线程改为了多线程进行垃圾回收,这样可以缩短垃圾回收的时间。当然了,并行垃圾收集器在收集的过程中也会暂停应用程序,这个和串行垃圾回收器是一样的,只是并行执行,速度更快些,暂停的时间更短一些。
ParNew垃圾收集器是工作在年轻代上的,只是将串行的垃圾收集器改为了并行。通过-XX:+UseParNewGC参数设置年轻代使用ParNew回收器。
ParallelGC收集器工作机制和ParNewGC收集器一样,只是在此基础之上,新增了两个和系统吞吐量相关的参数,使得其使用起来更加的灵活和高效。
3、CMS垃圾收集器
CMS全称ConcurrentMarkSweep,是一款并发的、使用标记-清除算法的垃圾回收器,该回收器是针对老年代垃圾回收的,通过参数-XX:+UseConcMarkSweepGC进行设置。
4、G1垃圾收集器(重点)
G1垃圾收集器是在jdk1.7中正式使用的全新的垃圾收集器,oracle官方在jdk9中将G1变成默认的垃圾收集器。
G1的设计原则就是简化JVM性能调优,开发人员只需要简单的三步即可完成调优:
1.第一步,开启G1垃圾收集器
2.第二步,设置堆的最大内存
3.第三步,设置最大的停顿时间(默认200ms)
G1中提供了三种模式垃圾回收模式,YoungGC、MixedGC和FullGC,在不同的条件下被触发。
原理:
G1垃圾收集器相对比其他收集器而言,最大的区别在于它取消了年轻代、老年代的物理划分,取而代之的是将堆划分为若干个区域(Region),这些区域中包含了有逻辑上的年轻代、老年代区域。这样做的好处就是,我们再也不用单独的空间对每个代进行设置了,不用担心每个代内存是否足够。











网友评论