垃圾回收
垃圾回收主要是针对堆和方法区。
其实方法区(MetaSpace)应当也是存储在堆中。
新生代中氛围Eden区 Suvivor0区 Suvivor1区 默认是8:1:1
老年代Tenured
对象会优先在堆中的Eden区中进行分配,当Eden中的空间不够之后,就会进行一次minnor gc
对象进入老年代的时机&&垃圾回收机制
当前对象如果是大对象,如果是大对象就会直接放入老年代,如果对象不是大对象,会先判断Eden区中能不能放入对象,如果Eden能放入就为其分配内存空间,如果放不下就去查看survivo区中能不能放得下,放得下就放,放不下了就进行一次minorGC,然后再检查能不能放下,如果可以放下就为其分配内存空间。
对象死亡的判断
1.引用其计数法,会为对象增加一个计数器,如果对象被引用,那么计数器就会+1,但是基本上没有虚拟机使用它来管理内存,因为存在循环引用问题
2.可达性分析法,需要找到一个GCroots,从gcroots开始向下搜索,gcroots走过的路径成为引用链,如果一个对象上没有任何引用链,那么这个对象就是没什么用的,需要进行回收。
-
虚拟机栈(栈帧中的局部变量表)中引用的对象
-
本地方法栈(Native 方法)中引用的对象
-
方法区中类静态属性引用的对象
-
方法区中常量引用的对象
-
所有被同步锁持有的对象
这些都可以作为GCRoots
方法区中进行回收的是无用的类,满足三个条件时,可以认为该类是一个无用的类
1.该类的所有实例对象都已经被回收了
2.加载该类的ClassLoader已经被回收
3.该类对应java.lang.Class对象没有在任何地方被引用,无法用反射去访问该类的方法
通常新生代中的gc被称为MinorGC 新生代中的对象没经一次MinorGC,其年龄就+1,如果年龄超过15就会进入老年代,当然这个阈值是可以修改的。
空间担保机制:在进行minorGC的时候会先进行判断,老年代中的连续空间是否大于新生代对象内存总大小或者新生代历次晋升老年带的平均内存,如果大于,那么就会进行MinorGC,如果不大于,那么就会进行FullGC
一般新生代主要是用的标记复制算法
老年带一般使用标记整理或者标记清除
为什么要分为新生代和老年代?
因为有的对象寿命长,有的对象寿命短。应该将寿命长的对象放在一个区,寿命短的对象放在一个区。不同的区采用不同的垃圾收集算法。寿命短的区清理频次高一点,寿命长的区清理频次低一点。提高效率。
STW:Stop The World 的缩写,意味着在GC的时候,其它线程无法工作。