jvm垃圾回收器和垃圾回收算法,jvm垃圾回收机制详解
00-1010垃圾收集算法的概念1。标记算法1.1引用计数)1.2可达分析)2算法2。回收算法2.1标记扫描)2.2算法2.2复制)2.3算法2.3标记压缩)2.4算法2.4分代回收算法概述
目录
00-1010垃圾收集(GC)。程序的运行是需要资源的,无效对象如果不及时清理就会一直占用资源,所以管理内存资源就变得非常重要。为了让我们更加关注代码本身,而不是过多考虑内存的释放,Java有了大家熟悉的GC。然而当垃圾回收成为系统达到更高并发量的瓶颈时,我们就需要对这些自动化的技术进行一系列的监控和调节。
GC主要需要完成三件事情 :
需要回收哪些内存?什么时候回收?怎么回收?有哪些垃圾需要回收?如何判断此时哪些物体是“活的”,哪些物体是“死的”?于是就有了标注算法。
在引用计数法和根可达算法.的00-1010垃圾收集器中有两种标记算法
00-1010引用计数算法非常简单。它实际上通过在对象头中分配一个空间来节省对象被引用的次数。如果该对象被其他对象引用,其引用计数将增加1。如果删除了对该对象的引用,其引用计数将减1。当对象的引用计数为0时,对象将被回收。
如:
A objA=new A();B objB=new B();objA.ref=objB如图:
对象A的实例只是Java堆中的一块内存,而objA将其作为局部变量引用,所以其引用计数为1,对象B的实例也是堆中的一块内存。objB把它作为局部变量引用,然后objA又引用了它,所以它的引用计数是2。
客观地说,引用计数算法是效率高,实现简单.但是,Java虚拟机没有选择引用计数算法来管理内存,主要是因为它无法解决循环引用的问题.
如:
objA.ref=objB奥布加如图:
实际上,这两个对象已经不能被访问了,但是因为它们相互引用,所以它们的引用计数不为0,所以这两个对象不能被GC回收。
00-1010在Java中,可达性分析算法用于判断一个对象是否有生命。选择一系列称为“GC根”的对象作为起点,并从这些对象开始向下搜索。搜索走过的路叫做参考链。当一个对象没有指向GC根的引用链时,它就是不可达的,这些对象将被判定为可回收的。
如图:
在Java中,可以用作GC根的对象包括
在虚拟机(堆栈框架中的局部变量表)中引用的对象的局部方法堆栈JNI(一般称为本机方法)中引用的对象在常量引用的对象方法区域中的类静态属性引用的对象方法区域中。
00-1010在成功区分哪些对象是活的,哪些是死的之后,GC的下一个任务就是进行垃圾回收,释放无用对象占用的内存空间,以便有足够的可用内存空间为新对象分配内存。常用的垃圾收集算法有标记清除算法、复制算法、标记压缩算法。.
00-1010标记清除算法是最基本的垃圾收集算法。就像它的名字一样,这个算法有两个过程:首先标记哪些对象是可回收的,然后回收内存。
标记:收集器从引用根节点开始遍历,并标记所有被引用的对象。普通
是在对象的Header中记录为可达对象。
清除: Collector对堆内存从头到尾进行线性的遍历,如果发现某个对象在其Header中没有标记为可达对象,则将其回收。从网上找张图给大家解释一下,
如图:
缺点:
1.效率不高,标记过程和清除过程效率都一般
2.会产生很多空间碎片,可能会导致以后为大对象分配空间时因为找不到可用的连续内存空间不得不再次进行GC。
2.2 复制算法(Copying)
GC复制算法(Copying GC)是由Marvin L. Minsky在1963年研究出来的算法。原理是把内存分为两个空间一个是From空间,一个是To空间,对象一开始只在From空间分配,To空间是空闲的。GC时把存活的对象从From空间复制粘贴到To空间,之后把To空间变成新的From空间,原来的From空间变成To空间。回收前后对比下图所示:
如图:
优缺点:
1.复制算法实现简单运行高效,不会产生内存碎片
2.但是将内存缩小为原本的一半,代价略高。
现在虚拟机基本都采用这种垃圾回收算法回收新生代
2.3 标记压缩算法(Mark-Compact)
标记压缩算法(Mark-Compact),标记过程和标记清除算法的标记过程一样,但是清理过程不同,会将存活对象移动到一端,然后清理掉端边界之外的内存,
如图:
优缺点:
标记整理算法效率低,但不用浪费内存,也不会造成内存碎片。
2.4 分代回收算法
因为新生代对象大量死去,少量存活,一般采用复制算法。老年代存活率高,回收的少,一般采用MC/MS(标记清除/标记压缩)
如图是我用arthas的dashboard命令输出的本地的Memory信息。jdk1.8默认的垃圾回收器是ps+po(这个之后讲)。可以看到新生代大小(伊甸区和s区),老年代大小。
2.4.1 新生代(Eden区/伊甸区)
年轻代的对象处于一种朝生夕死的状态,在年轻代的GC叫做YGC(Minor GC)。Eden区对象活过第一次垃圾回收之后会进入survivor区(S0S1/S1S2)。在S1,S2之间经过多次垃圾回收进入老年代。
-XX:MaxTenuringThreshold 可以配置多少次从年轻代进入老年代
在多线程那我们整过这张图,再看一下,分代年龄只有4bit,意味着对象的最大年龄只有15-----可以通过上面的参数设置大小,最大15,之后要是没有被gc就会进入老年代。
2.4.2 老年代(tenured/old)
进入老年代的对象大多数活过了年轻代的多次gc,因此不会频繁死亡,老年代的GC叫做(Major GC)FULL GC。FGC的效率比YGC低的多,在老年代无法继续分配空间的时候触发,触发是新生代老年代一起进行回收。
2.4.3 新生代何时进入老年代
1. 超过 XX:MaxTenuringThreshold 指定次数2. 动态年龄,S0->S1超过50%,把年龄最大的放到Old3. 分配担保:YGC期间,survivor区空间不够了,空间担保直接进入老年代
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注盛行IT的更多内容!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。