在内存空间中我们可以大致按照上图划分,将堆空间划分为,新生代,老年代,字符串常量池,封装类常量池。
回收机制主要进行在新生代和老年代。
新生代:
- 伊甸园:主要用于存放新创建的对象。
- 幸存区From,幸存去To:幸存去To空着,幸存区From存放已经存活有一定次数的对象。
老年代:
当幸存区From中对象的存活次数达到一定阈值(没有特殊情况就是这样,如果实在是没有空间,那么就会提前放入老年代),就放入老年代。
回收流程
新创建的对象都被放在了新生代的伊甸园中
当伊甸园内存不足时候,就会进行一次Minor GC(Minor GC采用的是 ‘复制’ 算法。),Minor GC会将伊甸园和幸存区FROM中存活的对象,
先复制到幸存去To中,并让其阈值+1.再交换From和To。
- 当再次创建对象,若新生代的伊甸园满了,则触发Minor GC(Minor GC采用的是 ‘复制’ 算法。),然后暂停其他线程(STW),只让垃圾回收线程工作,
这时不仅会回收伊甸园的垃圾,还会回收幸存区中的垃圾,再将活跃的对象复制到幸存去TO中,回收后然后交换FROM和TO。
然后让幸存去的对象阈值+1。
- 然后当幸存区中的对象超过某个阈值(最大为15,4bit),就会被放入老年代中。
- 如果新生代老年代中的内存都满了,就会先触发Minor GC(Minor GC采用的是 ‘复制’ 算法。),再触发Full GC,扫描新生代和老年代中所有不再使用的对象并回收
GC 分析
1、大对象处理策略
当遇到一个较大的对象时,就算新生代的伊甸园为空,也无法容纳该对象时,会将该对象直接晋升为老年代。
2、线程内存溢出
某个线程的内存溢出了而抛异常(out of memory),不会让其他的线程结束运行。
这是因为当一个线程抛出OOM异常后,它所占据的内存资源会全部被释放掉,从而不会影响其他线程的运行,进程依然正常。