java虚拟机初识(垃圾回收一)

183 阅读3分钟

一位刚刚学习垃圾回收的萌新,请路过的大佬指点一哈。好了,就谈谈我这位码畜对垃圾回收的理解,想要了解java的垃圾回收机制我们首先要了解在java中对垃圾的内存划分和我们所使用的垃圾回收算法:

我们来看一下虚拟机是怎样分辨一个对象到底是不是一个无用的对象

引用计数算法

首先我们给对象创建一个引用计数器,当有一个地方引用到这个对象的时候,我们给这个对象的计数器数值加一,反之,当这个引用失效的时候,就给这个计数器的数值减一,当计数器的数值为零时,这个对象就是一个没用的对象,java虚拟机就把这个对象回收了。但是他有一个缺点是无法解决对象之间的相互循环引用,当a对象持有b对象的引用,b对象也持有a对象的引用的时候,他就很难解决这个问题。比如:a.id=b,b.id=a。(这不是java使用的算法)

根搜索算法

在java中判断对象是无用对象的算法是根搜索算法,它通过一系列名为“GC Roots”的对象作为起始点,从这些节点往下搜索,搜索所走过的路径被称作引用链,当一个对象到“GC Roots”不存在任何的引用链时,那么就证明这个对象是一个无用的对象,java虚拟机就会回收。(其中“GC Roots”对象包括虚拟机栈中引用的对象,方法区中静态属性引用的对象,方法区中常量引用的对象,Native的引用对象)

java垃圾回收算法

标记—清除算法

先把所有需要被回收的对象标记出来,然后一次性的把被标记的对象清除掉。他的缺点主要是标记和清除的效率都不高,而且标记清除以后容易留下大量不连续的空间,从而当我们要在此分配比较大的对象的时无法找到连续的内存,就会在此触发垃圾回收来找到足够大的连续的内存。

标记—整理算法

这是在标记—清除算法的基础上提出的,在标记完数据的时候我们并不马上回收对象,而是将存活的对象都朝一段移动,然后清除掉边界外面的内存,这样就能解决内存碎片化的问题。

复制算法

上面说了,如何解决碎片化的问题,那么效率的问题怎么解决,复制收集算法就是解决这个问题的。他将内存分为相同的两块,每次使用其中的一块,当触发垃圾回收时,就将还存活的对象复制到另一块上,然后把这块内存中使用的内存一次性全部清除掉。他的缺点是每次只能使用内存的一半,代价有点高。但是经过研究发现大部分被创建的对象都活不过第一次的垃圾回收,因此不必用一比一的比例来分配内存空间,它使用一块比较大的Eden和两块比较小的Survivor,每次只使用Eden和其中一块Survivor,当发生垃圾回收时,把这两块中存活的对象对复制到另一块Survivor中。

分代收集算法

java虚拟机把堆划分为老年代和新生代,根据各个年代的特点来采用不同的垃圾回收算法。在新生代中,每次的垃圾回收中都有大量的对象死去,只有少量的对象存活,我们使用复制算法将少量的存活对象复制到另一块Survivor中。在老年代当中,对象的存活率高,我们使用“标记-整理”。