Detailed JVM garbage collection algorithm

Foreword

In the new generation will be divided JVM heap memory model, two years old and areas, the main area of ​​difference between the two is that the new generation of storage shorter survival time of the object, the old store's survival time longer objects, in addition to different survival time in addition, there are different garbage collection strategies, the following collection algorithm in the JVM:

  • Clear labeling
  • Tags to organize
  • Replication algorithm
  • Generational collection algorithm

With garbage collection algorithm, if it is determined that the object is JVM garbage objects is it? Determining whether an object has survived JVM will have their own sets of algorithms to determine:

  • Reference count
  • Reachability analysis

With the presence of these two concepts garbage collection and determination target, analyze them again gradually.

JVM is how to determine whether the object alive?

If it allows developers to determine whether an object is useful is very simple, simply put, is: 对象没有任何引用it considers the object can be recovered. Consider the following program code:

public class App {

    public static void main(){
        checkFile("/");
    }

    public static boolean checkFile(String path ){
        File file = new File(path);
        return file.exists();
    }
}

Program to implement the call checkFilewhen the JVM Figure probably like this:

To checkFileafter the completion of the implementation of the method, it is inside the local variables filewill be cleared along with the stack frame, this time also survive in the JVM heap the File object is useless:

If people judge very clearly found File object has been useless, that it replaced JVM is how to determine whether an object is able to survive it?

Reference count

Reference counting algorithm principle is relatively simple, there is Imagine objects that have a countproperty, each time a reference to the object will cause the countplus 1, assuming JVM when determining whether the object is alive to check the countproperty and found that this property is not 0 Description there are references to other objects in the object.

Until checkFileafter completion of execution method will count becomes 0 1 Save:

As a JVM it is easy to determine whether an object survived.

However, the reference count has an obvious drawback is that the problem can not be solved, such as circular references: A -> B -> A relationship such that an object is no way to determine whether an object should not recovered.

GC Root (reachability analysis)

为什么会被称为可达性分析算法呢?可以这样理解如果通过GC Root能到达一个对象那么这个对象就是存活的。那什么样的对象才是GC Root呢?

在Java语言中,可作为GC Roots的对象包括下面几种:

  1. 虚拟机栈中引用的对象(栈帧中的本地变量表);
  2. 方法区中类静态属性引用的对象;
  3. 方法区中常量引用的对象;
  4. 本地方法栈中JNI(Native方法)引用的对象。

还是用上面的例子,在checkFile方法执行时,因为栈帧变量file可做为GC Root所以在执行期间JVM是绝对不会回收掉这个File对象:

但是等到checkFile执行完成之后,这个栈帧会被弹出,其中的变量也会被释放,相应的没有GC Root能到达堆中的File对象,这个时候就可以判断这个对象是一个无用的对象了,然后安全回收。

垃圾收回算法

标记清除

这种算法分两分:标记、清除两个阶段,
标记阶段是从根集合(GC Root)开始扫描,每到达一个对象就会标记该对象为存活状态,清除阶段在扫描完成之后将没有标记的对象给清除掉。

用一张图说明:

这个算法有个缺陷就是会产生内存碎片,如上图B被清除掉后会留下一块内存区域,如果后面需要分配大的对象就会导致没有连续的内存可供使用。

标记整理

标记整理就没有内存碎片的问题了,也是从根集合(GC Root)开始扫描进行标记然后清除无用的对象,清除完成后它会整理内存。

这样内存就是连续的了,但是产生的另外一个问题是:每次都得移动对象,因此成本很高。

复制算法

复制算法会将JVM推分成二等分,如果堆设置的是1g,那使用复制算法的时候堆就会有被划分为两块区域各512m。给对象分配内存的时候总是使用其中的一块来分配,分配满了以后,GC就会进行标记,然后将存活的对象移动到另外一块空白的区域,然后清除掉所有没有存活的对象,这样重复的处理,始终就会有一块空白的区域没有被合理的利用到。

两块区域交替使用,最大问题就是会导致空间的浪费,现在堆内存的使用率只有50%。

分代回收

新生代回收

JVM的堆分为新生代和老年代,两种类型有不同的特性,根据它们的特性来选择不同的回收算法,这种算法会将新生代划分为一块Eden和二个Survivor区:

如上面的图有三块区域它们会按照8:1:1的比例进行分配,如1000m的堆Eden是800m,二个Survivor各占100m,那它们是如何运行的呢?

  1. 始终会有一块Survivor是空着的,内存使用率是90%
  2. 程序运行会在Eden和其中一块Survivor 1中分配内存
  3. 等到执行Minor gc,会将存活下来的对象移动到空着的Survivor 2
  4. 然后在EdenSurvivor 2中继续分配内存,Survivor 1空着等着下次使用

这样就能使内存使用率达到90%,也不会产生内存碎片。

老年代回收

老年代对象即使进行了垃圾回收,对象的存活率也高,所以采用标记清除或标记整理算法都是不错的选择,这里就不做阐述。

Guess you like

Origin www.cnblogs.com/xwgblog/p/11703104.html