Java垃圾收集和Android垃圾收集其实本质上差不多一样。
下面就来谈谈Java垃圾收集
垃圾收集对象:堆里的对象,因为栈中的基本数据类型用完后会及时释放掉存储空间
Java虚拟机采用分代收集,将堆中对象分为新生代和老生代,在新生代收集的时候只需要扫描新生代,而不需要扫描老生代。
垃圾收集在收集一个对象时会判断是否引用指向对象,在Java中的引用主要有4种:分别是Strong reference、Soft reference、Weak reference、Phantom reference
(1)强引用Strong reference,是Java一种默认采用的一种方式,我们平时创建的引用都属于强引用。如果一个对象没有强引用,那么该对象就会被回收
(2)软引用Soft reference,软引用的对象在垃圾收集时不会被回收,只有当内存不够用时才会真正地回收,因此软引用适合缓存的场合,这样会使得缓存中的对象可以尽量地在内存中呆久一点。
(3)弱引用Weak reference,弱引用有利于对象更快的被回收,弱引用的对象在垃圾收集时肯定会被回收
Java虚拟机垃圾收集算法
对新生代采用标记—复制算法(因为每次垃圾收集时都发现有大批对象死去,只有少量存活,所以用复制算法,用少量存活对象的复制成本就可以完成收集)
对老生代采用标记—整理算法(因为老生代中对象存活率高、没有额外空间对它进行分配担保,所以采用标记—整理算法)
标记—复制算法
(1)将内存按容量划分为大小相等的两块,每次只使用其中一块。当这一块内存用完后,就将还存活的对象复制到另外一块内存上,然后再把已使用过的内存空间一次清理掉.
复制算法实现简单,运行效率高,但是由于每次只能使用其中的一半,造成内存利用率不高。现在Java虚拟机都是用复制方法来收集新生代,由于新生代大部分都是朝生夕死的,所以两块内存比例不是1:1,而是8:1.当那个一份(Survivor)不够用时需要依赖其他内存(老生代)进行分配担保
标记—整理算法(改良的标记—清除)
(1)标记从GC Root开始扫描的每个对象(存活的对象)
(2)在标记完成后对所有存活的对象(有标记)都向一端移动,然后直接清理端边界以外的内存。这样提高了内存的利用率。
Android虚拟机最常用的算法便是标记—清除算法。
(1)标记出所有活动对象
(2)回收内存
缺点:需要标记和清除阶段吧所有对象停止执行。在垃圾回收器运行过程中,应用程序必须暂时停止,并等到垃圾回收器全部运行完成后,才能重新启动应用程序运行。
为了运行垃圾收集,需要停止虚拟机的运行,这可能会导致程序比较长时间的停顿。垃圾收集的主要工作在标记阶段,为了缩短停顿时间,Dalvik虚拟机使用concurrentmark技术。
concurrentmark技术:引入一个单独的是垃圾收集线程去标记,但是在运行清除阶段,必须停止虚拟机的运行。(Sweep阶段还是会重新运行mark)