jvm内存模型里面一个区域叫做堆,相信大家都不陌生(如果不知道的可以百度查看)
我们创建的对象都是存放在堆里面的,但是堆的内存是有限的,当达到一定容量的时候系统就会异常,这个时候我们就需要回收处理掉那些不在被使用的内存空间,下面我将从垃圾收集器和垃圾回收算法来简单明了的接受一下。
1:什么垃圾?
内存中已经不再被使用的空间就是垃圾
2:何时才被回收?
2.1:引用计数法 (不建议使用)判定,堆中每一个对象都有一个引用计数,当一个对象被创建时就将该对象实例分配给一个变量,该变量计数设置为1。当任何其他对象被赋值为这个对象的引用时,这个变量加1,但当一个对象的引用超过了生命周期或者重新设置为了一个新值时,引用计数减一,引用计数为0的对象实例可以被当做垃圾回收
缺点:每次对象赋值都要维护引用计数,且计数器本身也有一定的消耗,而且对于循环引用检测很难
2.2:可达性分析法,目前使用,从一个节点的GC ROOT 开始,寻找对应的引用节点,找到这个节点以后,继续寻找这个节点的引用节点,当所有的引用节点寻找完后,剩下的节点被当做没有被应用的节点,即无用的节点,无用的节点被看做是可以垃圾回收的。
GCROOT?1:虚拟机栈中的引用 2:本地方法栈中的引用 3:方法区类静态属性的引用 4:方法区中常量的引用
3:垃圾收集器
3.1:serial 串型垃圾收集器,它为单线程环境设计只使用一个线程进行垃圾回收
3.2:Parallel 并型垃圾收集器,多个垃圾收集线程并行工作,此时用户线程时暂停的(适用于科学计算/大数据处理等弱交互场景)
3.3:CMS并发垃圾收集器,用户线程和垃圾收集线程同时执行(不一定并行可能交替,不需要停顿用户线程,互联网公司使用较多,对响应时间要求搞的场景)
3.4:G1垃圾收集器,适用于堆内存很大的情况下(将内存分割成不同的区域然后并发的对其进行垃圾回收)
4:垃圾回收算法
4.1复制算法: 将内存区域分为两块内存区间,每次只使用其中的一块内存区间,当其中一块进行垃圾回收之后,将没有被回收的对象复制到另一块空间里,然后把使用的那块内存空间进行清理,这样就能保证中有一块空间是空闲的,没有碎片的产生,只需要移动堆顶指针,按顺序分配即可,实现简单,运行效率高,代价是浪费了一半的内存空间。(一般年轻代使用此算法)
4.2:标记整理算法:标记需要回收的对象 ,剩下的对象移动到一端,然后将端外空间进行清理,不会产生碎片
4.3:标记清除:标记处需要回收的对象,然后将这些标记的对象进行回收,不足:标记和清除效率低,这种标记清除后,容易产生大量的不连续的内存碎片,造成后续如果有大的对象将找不到大的内存空间进行存放,无法找到足够的连续内存时将会触发另一个垃圾收集动作
4.4:分代收集算法:这种算法更据对象的存活周期不同,分成不同的内存空间,主要包括:Eden,Survivor,Old,Humongous(特殊的old类型,放置大对象),优先回收垃圾最多的区域。
5:不同时期需要哪种收集器?
5.1:youngGen
Serial 收集器,单线程,一个cpu或者一条收集线程去完成垃圾收集工作,收集时需要暂停用户线程,默认的新生代收集器,使用垃圾回收算法是:标记复制
ParNew 收集器:是Serial 收集器的多线程版本,是默认的新生代收集器,除了Serial 收集器外只能和CMS(老年代)收集器配合使用
Parallel Scavenge(并行收集器) 收集器:是一个新生代收集器,它也是使用复制算法的收集器,是一个并行的多线程的垃收集器 (吞吐量优先收集器),吞吐量只指的是:用户线程运行代码的时间/(用户线程运行代码的时间+垃圾回收的时间),通常和Parallel Old 结合使用,Parallel Old 老年代收集器 ,在注重吞吐量以及cpu资源敏感的场合可以优先考虑 Parallel Scavenge(年轻代) 和Parallel Old (年老代) 收集器(PS Mark Sweep并行-标记-清楚),jdk1.8默认的就是这种
5.2:old gen
serial Old 垃圾回收算法(标记-整理) 收集器 是serial 收集器的老年代版本,同样也是一个单线程的垃圾收集器,暂停所有用户线程
Parallel Old 收集器:吞吐量优先收集器,上边说过一般和Parallel Scavenge(年轻代) 收集器结合使用
CMS(Concurrent Mark Sweep 并发标记清理算法) 以获取最短回收挺顿时间的收集器,注重服务器响应速度的可以使用这种垃圾回收算法、
6:了解下CMS(concurrent-mark-sweep)收集器(并发收集器)
CMS 垃圾回收的步骤氛围一下几种:
1:初始标记(CMS-initMark)-stop the word
2:并发标记(Concurrent mark)
3:重新标记(Rmark) -stop the word
4:并发清除(concurrent sweep)
初始标记:仅仅是记录下GCRoot能直接关联到的对象速度很快(GCroot我前面讲了)
并发标记:就是进行gcroot trancing(跟踪)的过程
重新标记:是为了修正并发标记期间程序继续运作导致标记产生变动的一部分对象的标记记录,这个阶段比初始标记长,比并发标记短
并发清除: 垃圾回收的线程和用户线程同时执行
Cms 的特点是:并发收集,低停顿
CMS收集器的缺点
1:CMS收集器对cpu资源非常敏感,默认启动的回收线程数是(cpu+3)/4 当cpu是4个时,并发垃圾回收线程不少于线程的25%
2:无法处理浮动垃圾(并发清理时,用户线程产生的垃圾)
3:由于CMS是基于标记-清除算法,会产生大量垃圾碎片,这样会导致没有连续的大内存来分配给大对象
7:了解G1垃圾收集器?
底层原理:
1:Region区域化垃圾收集器(最大好处是化整为零,
G1将java 堆分割成了若干个相同大小的区域(region) 包括Eden,Survivor ,old,Humongous(特殊的old类型),整体变为了
一系列不连续的内存区域,避免了全内存区域的GC操作
特点
1:整体上G1采用的是标记-整理算法,局部是通过复制算法,不会产生产内存碎片
2:宏观上G1不在区分年轻代和年老代,把内存划分为多个独立的子区域
3:保留了新生代和年老代,但他们不再是物理隔离,而是一部分Region 的集合且不需要Region
是连续的,也就是说依然会采用不用的GC方式来处理不用的区域
4:G1收集器虽然是分代收集,但整个内存分区不存在物理上的年轻代与年老代的区别,也不需要
完全独立的survivor (to space ) 堆做复制准备,G1只有逻辑上的分代概念,或者说每个分区
都可能随G1的运行在不同的代之间前后切换
G1的concurrent Marking分为5个步骤
第一步:Inital Mark 其实就是young GC,该阶段会引起stw 会标记gcroot直接可达的对象
第二步:Root Region Scan 根区域扫描,该阶段不会引起stw,它会并发的标记从上一阶段存活的区域扫描的老年代对象
第三部:concurrent mark 并发标记,改阶段从堆中标记存活的对象,与cms类似
第四步:Remark,即重新标记,改阶段会引起stw,与cms类似
第五步:Cleanup 主要为接下来的Mixed GC做准备,该阶段会优先统计出区域中存活的对象,并将待回收区域按回收价值排序,优先回收垃圾最多的区域
G1垃圾回收器的优势是
1.优先回收垃圾最多的区域
2:采用的是Mark-copying 回收算法,有很强的空间整合能力,不会产生大量碎片
3:G1的一大优势是在于可预测的停顿时间,能够尽可能快的在指定的时间内完成垃圾回收任务
G1收集器参数配置实例:-XX:UseG1GC -Xmx32g -XX:MaxGCPauseMills=100 开始g1+设置最大堆内存+设置最大停顿时间
-------------------------------------------------
喜欢的点个赞,不对的地方还希望指出!大家共同进步!
留言与评论(共有 0 条评论) |