垃圾收集器(一)

1.1 概述

垃圾收集器(Garbage Collection ,GC):Java语言中会自动对垃圾进行回收。可是GC须要完成它的功能是就必须思考:算法

  1. 那些内存须要回收?
  2. 何时回收?
  3. 如何回收

Java内存运行时区域的包括有,程序计数器、虚拟机栈、本地方法栈、Java堆、及方法区。其中:程序技术其、虚拟机栈、本地方法栈区域随线程而生,随线程而灭。栈中的栈帧随着方法的进入和退出而有条不紊的执行着出栈和入栈操做。所以这几个区域的内存分配和回收是具有肯定性的。Java堆和方法区则不同,一个接口中的多个实现类的内存可能不同,一个方法的多个分支须要的内存也不同,因此这部分的内存分配和回收都是动态的。spa

1.2 须要回收的内存

通常而言,在堆中存放着Java世界中几乎全部的对象实例。垃圾收集器对内存是否须要回收的标准——对象是否被引用。线程

1.2.1 引用计数算法

给对象添加一个引用计数器,当一个地方应用它时,计数器就加1;当引用失效是,计数器减1。当计数器的值为1时,则断定该对象不可能在被引用。对象

其优势:实现简单、断定效率高;接口

缺点:难以解决对象中之间互相循环引用的问题。内存

1.2.2 可达性分析算法

在主流的商用语言中,主要是采用可达性分析算法(Reachability Analysis)来判断对象是否可达。思路:采用“GC Roots”的对象做为起始点,从这些节点向下搜索,搜索所走过的路称为“引用链”,当一个对象同过引用链能够和“GC Roots”链接是,则对象不可回收,不然回收对象。虚拟机

Java 语言中,可做为GC Root的对象包括有如下几种:it

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

通常而言,就是定义的常量。io

1.2.3 引用

以可达性分析算法区分对象是否被引用仍是过于简单了。对于某些对象,也许须要对象,当内存空间还足够时,将其保留在内存中,不然进行垃圾收集。效率

所以,将引用在分为:强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference.

强引用:垃圾回收器永远不会回收该对象,(形成内存泄漏的主要缘由之一);

软引用:当内存充足时,对象不会被回收,不然回收该对象。一般适用于内存空间敏感的地方。内存不够是,进行垃圾回收。回收以后若是尚未足够的内存,会抛出内存溢出异常;

弱引用:当垃圾回收器运行时,不管是否内存足够,会直接回收内存;

虚引用:一个对象是否有虚引用存在,彻底对其生存时间产生不了影响,也没法经过虚引用来取得一个对象的实例。其存在的惟一目的是定位对象被垃圾收集的位置。

1.3 垃圾回收算法

1.3.1 标记-清除算法

好比教室若是要更换桌子,咱们能够先遍历一下那些桌子是坏并标记,而后在遍历一下桌子是否有标记,把有标记的桌子抬出去。标记-清除算法顾名思义是先标记,再清除。这是最简单的收集算法,容易实现。

缺点:1.须要遍历两遍,效率不高;

2).产生间断性的内存碎片;

1.3.2 复制算法

复制算法是但咱们知道对象存活率较低时,能够把还存活的对象格外放在一块区域,而后将另外一区域的对象所有回收。

所以,把内存分为一个较大的Eden空间和两个较小的Survivor区间。HotSpot默认的二者比例数8:1

1.3.3 标记-整理算法

若是对象存活率较高时,能够采用“标记-整理算法”。先将能够回收的对象进行标记,而后让全部可存活的对象向一端移动,直接清除边界之外的内存。

1.3.4 分代收集算法

当前Java虚拟机大多采用分代收集算法。思想是,根据对象的存活周期的不一样将内存分为几块。通常讲Java分为新生代和老生代。通常而言,新生代有98%的对象是能够被回收的,所这里通常采用复制算法。老年代存活率比较高,能够采用“标记-清除”或者“标记整理”法。

相关文章
相关标签/搜索