• 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html
  • 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html

Java虚拟机JVM复习之垃圾回收

极客笔记 巷子的童年 3个月前 (03-02) 133次浏览 已收录 0个评论 扫描二维码
1.如何确定哪些对象需要回收?
1)引用计数算法
对于创建的每一个对象都有一个与之关联的计数器,这个计数器记录着该对象被引用的次数,垃圾收集器在进行垃圾回收时,对扫描到的每一个对象判断一下计数器是否等于0,若等于0,就会释放该对象占用的内存空间,同时将该对象引用的其他对象的计数器进行减一操作。
算法的优点:使用引用计数器,内存回收可以穿插在程序的运行中,在程序运行中,当发现某一对象的引用计数器为0时,可以立即对该对象所占用的内存空间进行回收,这种方式可以避免FULL GC时带来的程序暂停
算法的劣势:采用引用计数器进行垃圾回收,最大的缺点就是不能解决循环引用的问题(或者说相互引用,即相互等待对方被回收自己才能回收)。
2)根搜索算法(可达性分析算法)
通过一系列的称为“GC Roots”的对象为起点,从这些节点出发往下搜索,如果能搜索到的对象,称为可达对象,搜不到的对象就可以认为不可达对象,可以被回收。
可作为GC Roots的有(即不进行可达性分析就能判断其不需要回收的对象):
1)栈帧中的本地变量表中引用的对象;
2)方法区中类静态属性引用的对象、常量引用的对象(因为方法区一般不会被回收、因此其引用的对象也不能被回收);
3)本地方法栈中JNI(即一般说的Native方法)引用的对象。
2. 如何清理垃圾(垃圾收集算法)
1)标记清除算法
当堆中的有效内存空间被耗尽的时候,就会停止整个程序,然后进行两项工作,标记和清除。
标记:标记的过程其实就是,遍历所有的GC Roots,然后将所有GC Roots可达的对象标记为存活的对象。
清除:清除的过程将遍历堆中所有的对象,将没有标记的对象全部清除掉(释放对象所在的空间)。
为什么非要停止程序的运行呢?
假设A已经被标记为可清除,此时在程序当中又new了一个新对象B,且A对象可以到达B对象。但是由于此时A对象已经标记结束,此时B对象还是不可达,因为它错过了标记阶段。因此当接下来轮到清除阶段的时候,新对象B将会被清除掉。如此一来,GC线程将会导致程序无法正常工作。
缺点:1)效率问题:它需要递归(标记)和全堆对象遍历(清理),在GC时还需要停止应用程序(不利于交互性的应用程序)。
2)产生大量碎片,不容易找到大块连续内存来存储大对象。为此提出后面两种改进算法。
2)复制算法
复制算法将内存划分为两个区间,在任意时间点,所有动态分配的对象都只能分配在其中一个区间(称为活动区间),而另外一个区间(称为空闲区间)则是空闲的。当有效内存空间耗尽时,JVM将暂停程序运行,开启复制算法GC线程。接下来GC线程会将活动区间内的存活对象,全部复制到空闲区间,且严格按照内存地址依次排列,与此同时,GC线程将更新存活对象的内存引用地址指向新的内存地址,同时还驻留在活动区间的垃圾对象就会被一次性清理
优点:解决了产生垃圾碎片的问题,缺点是一半内存空间不能用,同时如果对象的存活率很高,那么复制将花费大量时间、效率不高。
3)标记整理算法(压缩)
标记过程仍然和上述算法一样,在清理阶段时将所有存活的对象向一端移动,然后清除存活区域之外的对象即可。
优点:不会产生内存碎片。
4)分代收集算法
就是根据对象存活周期的不同将内存划分为几块,根据各个年代的特点采用合适的收集算法
优点:1.首先就是分代回收可以对堆中对象采用不同的gc策略。在实际程序中,对象的生命周期有长有短。进行分代垃圾回收,能针对这个特点做很好的优化。例如在新生代,对象“朝生夕死”。gc一般采取复制算法,因为此算法的突出特点就是只关心哪些需要被复制,可达性分析只用标记和复制很少的存活对象。不用遍历整个堆,因为大部分都是要丢弃的。所以针对老年代对象的特点,一般采用标记-清理(有的算法会带压缩)策略的算法。这部分如果采用复制算法的话,一方面没有额外空间给其担保,另一方面由于存活率高,复制的开销显著增大。
2.分代以后,gc时进行可达性分析的范围能大大降低(只要对一部分数据进行分析)。

注:Minor GC:从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC;Major GC 是清理老年代;Full GC 是清理整个堆空间—包括年轻代和老年代。
新生代和老年代的回收策略:
(1)年轻代(Young1/4:Eden+Survior1/8,该比例保证只有10%的空间被浪费,保证每次回收都只有不多于10%的对象存活)=From+To,存放新创建的对象.
(2)老年代(Old ):存放几次垃圾收集后存活的对象。
(3)永久区(Perm区):存放类的Class对象Eden区满后触发minor GC,将所有存活对象复制到一个Survivor区,另一Survivor区存活的对象也复制到这个Survivor区中,始终保证有一个Survivor是空的。youngSurvivor满后触发minor GC后仍然存活的对象存到Old区,如果Survivor区放不下Eden区的对象或者Survivor区对象足够老了,直接放入Old区,如果Old区放不下则触发Full GCPerm区满将触发Major GC
3.基本面试题
强引用、软引用、弱引用、虚引用以及他们之间和gc的关系。
强引用:new出的对象之类的引用,只要强引用还在,永远不会回收。
软引用:引用但非必须的对象,内存溢出异常之前,回收 
弱引用:非必须的对象,对象能生存到下一次垃圾收集发生之前。 
虚引用:对生存时间无影响,在垃圾回收时得到通知。
4. 垃圾收集器
1.Serial(串行)收集器
是一个单线程收集器,只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是它在进行垃圾收集时,必须暂停其他所有的工作线程,直至Serial收集器收集结束为止(“Stop The World”),它依然是HotSpot虚拟机运行在Client模式下的默认的新生代收集器。简单高效(与其他收集器的单线程相比),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,因此可以获得更高的单线程收集效率。

2. ParNew收集器
ParNew收集器就是Serial收集器的多线程版本,它是一个新生代收集器。除了使用多线程进行垃圾收集外,其余行为与Serial收集器完全相同,是许多运行在Server模式下的虚拟机中首选的新生代收集器。目前只有它能与CMS收集器(老年代收集器)配合工作,ParNew在单cpu下性能比Serial差,但在多cpu下好,其默认开启与cpu数量相同的线程来进行垃圾收集。

3.Parallel 收集器
Parallel Scavenge收集器也是一个并行的多线程新生代收集器,它也使用复制算法,他的目的是为了达到一个可控制的吞吐量。
吞吐量=运行用户代码的时间/总时间。
4. CMS收集器

标记过程分三步:并发标记是最主要的标记过程,而这个过程是并发执行的,可以与应用程序线程同时进行,初始标记和重新标记虽然不能和应用程序并发执行,但这两个过程标记速度快,时间短,所以对应用程序不会产生太大的影响。最后并发清除的过程,也是和应用程序同时进行的,避免了应用程序的停顿。CMS的优点,减少了应用程序的停顿时间,让回收线程和应用程序线程可以并发执行。它的回收并不彻底。因此CMS回收的频率相较其他回收器要高,频繁的回收将影响应用程序的吞吐量
CMS何时开始?
cms gc 通过一个后台线程触发,该线程随着堆一起初始化,触发机制是默认每隔2秒判断一下当前老年代的内存使用率是否达到阈值,如果高于某个阈值的时候将激发CMS。
总结一下:
CMS采用了多种方式尽可能降低GC的暂停时间,减少用户程序停顿。
停顿时间降低的同时牺牲了CPU吞吐量 。
这是在停顿时间和性能间做出的取舍,可以简单理解为”空间(性能)”换时间
G1回收器是jdk1.7以后推出的回收器,试图取代CMS回收器。
不同于其他的回收器、G1将堆空间划分成了互相独立的区块。每块区域既有可能属于老年代、也有可能是新生代,并且每类区域空间可以是不连续的(对比CMS的老年代和新生代都必须是连续的)。这种将老年代区划分成多块的理念源于:当并发后台线程寻找可回收的对象时、有些区块包含可回收的对象要比其他区块多很多。虽然在清理这些区块时G1仍然需要暂停应用线程、但可以用相对较少的时间优先回收包含垃圾最多区块。
G1相对CMS回收器来说优点在于:
1、因为划分了很多区块,回收时减小了内存碎片的产生;
2、G1适用于新生代和老年代,而CMS只适用于老年代。
g1cms区别,吞吐量优先和响应优先的垃圾收集器选择
CMS收集器:一款以获取最短回收停顿时间为目标的收集器,是基于“标记清除”算法实现的,分为4个步骤:初始标记、并发标记、重新标记、并发清除。 
G1收集器:面向服务端应用的垃圾收集器,过程:初始标记;并发标记;最终标记;筛选回收。整体上看是“标记整理”,局部看是“复制”,不会产生内存碎片。 
吞吐量优先的并行收集器:以到达一定的吞吐量为目标,适用于科学技术和后台处理等。 
响应时间优先的并发收集器:保证系统的响应时间,减少垃圾收集时的停顿时间。适用于应用服务器、电信领域等。

丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:Java虚拟机JVM复习之垃圾回收
喜欢 (0)
[247507792@qq.com]
分享 (0)

您必须 登录 才能发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00