接着学习jvm相关内容,上一篇文章学习了jvm的内存结构,接下来学习一下垃圾回收机制是如何运作的。
判断对象是垃圾的方法
核心就是判断一个对象在new出来之后,程序是否还使用它。
曾经通过一个对象有几个引用来判断,计数有几个引用,如果计数归零,那么就回收,如果不为零,那么就不回收。
但是这样就有一个bug。
比如循环引用,两个对象循环引用的话,两个对象的引用计数都是1,那么永远都不会触发回收,所以这种判断方法不行。
那么现在使用什么方法判断呢?
GC Roots,可达性分析算法。
所有还没有回收的对象都有一个根节点,从根节点触发,能到达的对象,就不用回收。到达不了的对象就要回收了。
GC Root不止一个,可以很多。很多对象都可以当GC Root。
比如:
- VM stack里面的局部变量
- 方法区里面的静态变量
- 方法区里面的常量。
如何回收?
有三种回收的手段:
- 标记,然后清除
- 标记,然后复制
- 标记,然后整理
标记,清除
直接从内存抹除,但是会产生内存碎片。如果此时需要new一个需要大片连续内存的对象,就会报错。
标记-复制
内存分两半,平时用一半,清理的时候,将不用回收的对象都复制到另一半内存去,将原来一半内存清除。这样就没有内存碎片啦。
但是这样的话,可用内存就少了很多。
标记-整理
先抹除内存,然后逐步将不用回收的对象移动,整理。 这样就可以没有内存碎片,而且不浪费内存啦。
但是也有缺点,移动对象的时候,对象就不能用了,对象相关的代码也就得暂停。