1、什么事垃圾回收
#C/C++语言的垃圾回收
1)在C/C++语言中,没有自动垃圾回收机制,是通过new关键字申请内存资源,通过delete关键字释放内存资源
2)如果程序员在某些位置没有写delete进行释放,那么申请的对象将一直占用内存资源,最终可能会导致内存溢出
#java语言的垃圾回收
1)Java语言中,有自动的垃圾回收机制,也就是我们熟悉的GC
2)GC精髓在于算法,如果算法不合理一样会内存溢出
2、垃圾回收的常见算法
#引用计数法
1)原理
假设有一个对象A,任何一个对象对A的引用,name对象A的引用计数器+1,当引用失败时候,对象A的引用计数器就-1,如果对象A的计数器值为0,就说明对象A没有引用了,可以被回收
2)优点
1、实时性较高,无须等到内存不够的时候,才开始回收,运行时候根据对象的计数器是否为0,就可以直接回收。
2、在垃圾回收过程中,应用无需挂起,如果申请内存时,内存不足,则立刻报outofmemory错误
3、区域性,更新对象的计数器时候,只影响到该对象,不会扫描全部对象
3)缺点
1、每次对象被引用的时候,都需要去更新计数器,有一点时间开销
2、浪费CPU资源,即使内存不够用,仍然在运行时候进行计数器的统计
3、无法解决循环引用问题(最大的缺点)
#标记清除法
1)标记清除算法是将垃圾回收分为2个阶段,分别是标记和清除
标记:从根节点开始标记引用的对象
清除:未被标记引用的对象就是垃圾对象,可以被清除
2)优点
标记清除算法解决了引用计数算法中的循环引用的问题,没有从root节点引用的对象都会被回收
3)缺点
1、效率较低,标记和清除两个动作都需要遍历所有对象,并且在GC时候,需要停止应用程序,对于交互性要求比较高的应用而言,这个体验非常差的
2、通过标记清除算法清理出来的内存,碎片化较为严重,因为被回收的对象可能存在于内存的各个角落,所以清理出来的内存是不连贯的
#标记压缩算法
1)原理
把所有使用的内存空间进行压缩排序移动,使得碎片空间完成变成完整的
#复制算法(初始的时候会开辟两个内存区域)
1)原理
S0如果内存空间放不下了,就开始触发GC操作,是的GC清理内存空间,然后把所有剩余对象空间按照顺序拷贝到S1
2)优点
1、在垃圾对象多的情况下,效率较高
2、清理后,内存无碎片
3)缺点
1、在垃圾对象少的情况下,不适用,如:老年代内存
2、分配的2块内存空间,在同一时刻,只能使用到一半,内存使用率较低
#分代算法
1)原理
根据回收对象的特点进行选择,在jvm中,年轻代适合使用复制算法,老年代适合使用标记清除或者标记压缩算法
#垃圾收集器的种类
1)Serial(串行垃圾收集器,GC线程只有一个,GC回收的时候要停止业务线程)
#串行垃圾收集器是最基本、发展历史最悠久的收集器
#特点;单线程、简单高效(与其他收集器的单线程相比),对于限定单个CPU的环境来说,Serial收集0器由于没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率,收集器进行垃圾回收时,必须暂停其他所有工作线程,直到它结束(Stop The World)
2)Parallel(并行垃圾收集器,GC线程有多个,但是只是在回收的时候多了处理收集器,还是需要停止业务线程,只是因为并行业务停止时间缩短了)主要使用场景,大数据做科学计算的
#并行垃圾收集器在串行垃圾收集器的基础之上做了改进,将单线程改成多线程垃圾回收,这样可以缩短垃圾回收的时间
#ParNew垃圾收集器
通过-XX:+UseParNewGC参数设置年轻代使用ParNew回收器,老年代使用的依然是串行收集器
通过-XX:+ParalelGCThreads可以限制GC线程使用数量,默认开启和CPU数目相同的线程数
只在新生代起作用,新生代使用并行垃圾处理器,老年代使用串行垃圾处理器
#并行垃圾收集器-ParallelGC运行示意图(吞吐量优先收集器)
新生代老年的并行化,可控制的吞吐量,高效率的高吞吐量,资源占用率比较高,这个收集器比ParNew更高端点,会自动分配调准参数
3)CMS
#CMS全称Concurrent Mark Sweep,是一款并发的、使用标记0清除算法的垃圾回收器,该回收器是针对老年代垃圾回收的,通过参数-XX:+UseConcMarkSweepGC进行设置
以获取回收停顿时间为目标的回收器。
注意:开启后将采用ParNew + CMS + Serial Old(默认启动这个串行垃圾回收器,是最后的担保机制启动后使用的,因为ConcMarkSweep这个回收线程和应用线程同时执行的,有可能出现垃圾回收没有执行完成,业务有需要内存从而内存溢出。进行保底)收集器组合
#CMS垃圾回收器的执行过程如下(回路):
1、idling(闲置等待)
2、InitialMarking(初始化标记)
3、Marking(并发标记)
4、Precleaning AbortablePreclean(预处理)
5、FinalMarking(重新标记)
6、Sweeping(并发清理)
7、Resizing(调整堆大小)
8、Resetting(重置)
#优点
并发高效,停顿间隔短,无差别停顿业务线程
#缺点
资源利用率高,容易形成空间碎片,不是实时进行清理
4)G1
#G1垃圾收集器在JDK1.7update4中正式使用的全新的垃圾收集器,oracle官网在jdk9中将G1变成默认的垃圾收集器,以替代CMS。
#G1垃圾收集器(将新生代,老年代的物理空间划分取消了),G1垃圾收集器(G1算法将堆划分为若干个区域-Region),每块区域大小默认32M,最大设置2048个区域,总共64G内存,肯定够用了
Eden,Survivor,Old,Humongous(超大区域)
#G1垃圾回收模式:
1、Young GC(年轻GC回收模式)
2、Mixed GC(混合GC回收模式)
1)全局并发标记(global concurrent marking)
2)拷贝存活对象(evacuation)
3、G1垃圾收集器相关参数
-XX:+UseG1GC
-XX:+MaxGCPauseMillis(指定垃圾回收的暂停时间,程序只能尽量按照这个时间进行设置)
-XX:+G1HeapRegionSize=n(1-32M,默认2048个分区,最大64G内存)
-XX:+G1ReservePercent=n(空闲的空间预留百分比,降低空闲空间溢出的风险,默认百分之十,基本上不用改)
-XX:+ConcGCThreads=n(GC的线程数不能超过CUP核数,超过没有意义只能使用到最多核数)
-XX:+InitiatingHeapOccupancyPercent=n(老年代大小占堆百分比达45%的时候出发mixed GC)
4、G1垃圾收集器 vs CMS垃圾收集器:
#G1不会产生碎片
#G1可以精准控制停顿,它把整堆划分为多个固定大小区域,每次根据停顿时间去手机垃圾最多的区域
5、G1垃圾收集器优化建议:
1)年轻代大小
#避免使用-Xmn 选项或者 -XX:NewRatio等其他相关选项显示设置年轻带大小
#固定年代的大小会覆盖暂停时间目标
2)暂停时间目标不要太过苛刻
#G1 GC的吞吐量目标是90%的应用程序时间和10%的垃圾回收时间
#评估G1 GC的吞吐量时,暂停时间目标不要太过苛刻,目标太过严苛表示您愿意承受更多垃圾回收开销,而这会直接影响到吞吐量
###############################
3、可视化GC日志分析工具
#GC日志输出参数:
-XX:+PrintGC 输出GC日志
-XX:+PrintGCDetails输出GC的详情日志
-XX:+PrintGCTimeStamps输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps输出GC的时间戳(以日期形式)
-XX:+PrintHeapAtGC在进行GC的前后打印出堆信息
-Xloggc:gc日志输出的路径
http://gceasy.io/ gc日志解析网站