什么是垃圾:没有被任何引用指向的对象或者多个对象(循环引用)
一、如何定位垃圾
- 引用计数:每当一个对象被引用时,引用计数加1,但是会出现循环引用的情况,即多个对象循环引用,但是没有外部对象访问他们那
-
根可达算法:从根节点去计算能够访问到的对象即不是垃圾,否则是垃圾
二、垃圾清除算法
标记清除:先标记所有需要被回收的对线,再统一清除
标记和清除的效率不高,而且会产生内存碎片,当碎片过多时,会使得大对象无法分配到内存,导致不得不提前GC,甚至Stop The World
复制算法:把内存区域均分,每次使用一块,当这片内存需要GC时,会把这片内存的存活内存移动到另外一个块中,循环往复
当对象存活率高时,复制次数多,效率低,且内存减少一半,但是没有碎片问题
标记-整理:把需要清除的垃圾先标记,然后再把存活对象都向一端移动,然后直接清除边界以外的内存
效率比复制算法低,但是不会产生碎片,也不需要额外的内存
二、堆内存逻辑分区
堆空间被分为新生代
和老年代
-
新生代
: 该区域用于处理对象频繁GC的场景,由于频繁创建对象,所以新生代会频繁触发MinorGC(YGC)进行垃圾回收,所以使用复制算法,当存活对象被移动到S区以后,直接清除其他所有新生区内存即可- eden:用于存放新建的对象(如果新创建的对象占用内存很大,则直接分配到老年代)
- Survivor(S0):存放上次没有被MinorGC回收的对象
- Survivor(S1):本次GC需要被扫描的对象 (还包括eden区)
即一次GC有一个Survivor区被用作存放,一个Survivor用作被扫描,,当多次循环MinorGC没有被回收的对象进入到老年代
老年代:存放大对象,以及被多次YGC都没有被回收的对象