Jvm垃圾回收机制
Jvm的内存区域
在jvm的自动内存管理急之下,不需要为每一个对象去写delete代码,不容易出现内存泄露或者内存溢出的问题。
判断对象已死的算法
在堆里面存放着各种java对象,垃圾收集器在对堆进行垃圾回收时,首要就是判断哪些对象还活着,哪些对象已经死去(即不被任何途径引用的对象)。
引用计数器算法:
引用计数器算法:给对象添加一个引用计数器,每当有一个地方引用该对象时,计数器+1,当引用失效时,计数器-1,任何时刻,当计数器为0的时候,该对象不再被引用。
如果出现,A调用B B调用A 这种情况 引用计算法就 无法完成垃圾回收
所以不推荐
可达性分析算法:
GC Roots 指的是:垃圾收集器的对象,GC收集那些不是GC Roots并且没有被GC Roots引用的对象。
通过一系列的称为GC Roots 的对象作为起始点,从这些节点开始向下搜索,搜索走过的路径成为引用链,当一个对象到GC ROOTS 没有任何引用链相连,则证明此对象是不可用的。
在java中,可以作为GC ROOTS的对象包括
虚拟机中引用的对象
方法区中静态属性引用的对象
方法区中的常量引用的对象
本地方发栈中jni 的引用对象
引用分为四种:
1、 强引用:在代码中普遍存在的,类似于 Object obj = new Object ,只要强引用一直存在,垃圾回收就永远不会回收被强引用的对象。
2、 软引用:用来描述一些还有用,但是并非必须的对象,当内存溢出异常发生之前,通过垃圾回收进行二次回收,如果二次回收之后,系统内存依然不够,才会抛出内存溢出异常。在jdk 1.2之后用 softreference类来实现
3、 弱引用:也是用来描述非必须对象的,弱引用相对于软引用的强度 还要弱一些,它只能生存到 下一次垃圾回收之前,当垃圾收集时,无论内存是否足够,都会被回收。在jdk1.2以后用weakreference类来实现
4、 虚引用:它是最弱的一种 引用关系,一个对象是否有虚引用的存在,完全不会对其生存时间产生影响,也无法通过虚引用来获取一个实例对象。它存在的唯一目的就是该对象被垃圾回收时收到一个系统通知。在jdk1.2以后用phantomreference类来实现
标记清除算法:会产生内存碎片,内存使用率 清除率不高
标记整理算法:不会产生内存碎片,内存使用率高。
复制算法:把内存分成两个一模一样大小的内存,一个区域当作预留内存 ,不存放对象, 所有产生的对象放在使用区域 ,垃圾回收时,把存活的对象依次复制到预留区,然后清除使用区域所有的对象。 使用区域就变成预留区 预留区变成使用区。 内存利用率也不高。
分代垃圾回收
根据内存的特点分为两个区域:
1、年轻代
2、老年代
年轻代:存放的朝生夕死的对象 收集频率高 产生快回收快
年轻代分为 Eden区 :存放对象 百分之九十的内存
from区 :存放 Eden区中存活的对象
To区 :存放 Eden from 区中存活的对象;
From和To占百分之十的内存
当第一次垃圾回收,Eden区的存活对象 复制到from区 , 清除 Eden
当第二次垃圾回收,Eden区存活的对象 与 from 区 存活的对象 复制到 to区 ,清除 Eden 和 from区。
当第三次垃圾回收,Eden区存活的对象和 to区存活的对象 又复制到 from区,清除 Eden和 to区。
From区 与 To区 循环的当作存放存活对象的容器。
如果 存活的对象占用内存 超过幸存区的大小 那么该对象直接进入老年代存放,这叫做内存担保机制。 或者一个对象在内存回收中存活超过15次 也直接复制到老年区
年轻代的每一次回收叫做 Minor Gc
老年代: 存放经常用的 不容易被回收的对象
老年代回收叫Full GC
垃圾收集器
年轻代收集器:
Serial收集器是最基本,发展最悠久的收集器 ,在jdk1.3之前是虚拟机新生代垃圾回收的唯一选择,它是一个 单线程的收集器,在收集时 其他工作线程会暂停 直到收集结束。
ParNew 收集器是Serial收集器的多线程版本,除了使用多线程进行垃圾回收之外 其余参数和算法好,停止工作线程,回收策略等 与Serial完全一致。
Parallel Scavenge 是一个年轻代收集器,才用复制算法,又是并行的多线程收集器,可以控制吞吐量(cpu运行用户线程的时间与cpu运行总时间比值)
吞吐量=(用户线程工作时间)/(用户线程工作时间+垃圾回收时间)
老年代收集器:
Serial Old 是Serial收集器的老年代版本,也是单线程 使用标记整理泛
Parallel Old收集器 是Parallel Scavenge的老年代版本,使用多线程标记整理算法,在jdk1.6才开始使用的
CMS 收集器是一种以获取最短停顿时间为目标的收集器,才用的是标记清楚算法,
他的过程分为四个步骤:
只有初始标记 和重新标记需要暂停用户线程
1、初始标记:关联GC Roots能直接关联的对象,速度快
2、并发标记:进行GC RootsTracing的过程
3、重新标记:为了修正并发标记期间,因为用户程序运作导致标记产生变动的那一部分对象。
4、并发清除
缺点:1、cms收集器对cpu资源非常敏感
2、无法处理浮动垃圾
3、因为标记清楚算法,所以会产生大量垃圾碎片。
G1收集器
Jdk1.9以后默认的垃圾收集器
原文:https://www.cnblogs.com/putin-feng/p/14225448.html