JVM是如何回收垃圾的?
Posted lllllLiangjia
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM是如何回收垃圾的?相关的知识,希望对你有一定的参考价值。
目录
前言
JVM如何回收垃圾其实就是GC操作,那GC操作的步骤是什么?
我们可以将它分为两个步骤:找垃圾和清除垃圾
说之前我们先明确两个概念
内存泄漏与内存溢出的区别
内存泄漏:已经使用过的内存没有及时的清空处理,长时间占用内存,导致内存空间不足,而出现内存溢出。
内存溢出:要求使用的空间超过系统能给的,系统不能满足需求,于是溢出。
如何找到垃圾?
可达性分析算法--目前JVM使用的
从GC Roots的根对象作为起点开始搜索,搜索过程所走的路径成为引用链,如果某个对象到GC Roots间没有任何引用链相连,那随时可被GC回收。
GC Roots对象包括
- 虚拟机栈中引用的对象,譬如各个线程被调用方法堆栈中使用到的参数、局部变量、临时变量
- 方法区中类静态属性引用的对象,譬如Java类的引用类型静态变量
- 方法区中的常量引用对象,譬如字符串常量池里的引用
- 所有被同步锁持有的对象
可达性算法判为不可达对象,也不是非死不可,宣告一个对象的死亡,至少要经过两个标记过程:
如果对象在进行可达性分析后没有发现与GC Roots相连接的引用链则第一次标记,随后进行筛选,判断是否有该对象的类重写了finalize()方法,如果没有则直接回收。如果有,将对象放在一个F-Queue队列中,之后去执行他们的finalize()方法,如果在这个方法中重新与引用链上的任何一个对象建立关联即可。
再回收时,如果第二次进行了标记,则直接回收
引用计数法--扩展
每个对象都有一个引用计数器,当对象被引用一次,计数器就加1,当对象引用时效一次就减,当计数器为0,意味着对象是垃圾对象,可以被GC回收。
注:环形垃圾无法回收
如何清除垃圾?
标记-复制算法
将内存一分为二,将有用的对象拷贝到新的一半内存区域
缺点:
将内存缩小为了原来的一半,空间浪费太多了
适用范围:
新生代区域使用,两个survivor区域每回收一次数据,都将其中的一个survivor区域有用的数据放到另一个survivor区域内。
标记-整理算法
首先标记出所有存活的对象,让他们都向内存空间一端移动,然后直接清理掉边界以外的内存。
缺点:
这种对象的移动操作必须全程暂停用户应用程序才能进行,这样的停顿被描述为“Stop The World”
适用范围:
老年代区域使用
标记-清除算法
首先标记出所有需要回收的对象,在标记完成后,统一回收掉所有被标记的对象。
缺点:
造成的问题碎片化严重
以上是关于JVM是如何回收垃圾的?的主要内容,如果未能解决你的问题,请参考以下文章
JVM day02 如何判断对象可以回收垃圾回收算法分代垃圾回收垃圾回收器