垃圾回收器执行垃圾回收主要做三个事情
1、哪些内存需要回收
2、什么时候回收
3、如何回收
-
哪些内存需要回收
1.引用计数器法:一个对象有一个引用指向他引用计数器就加一;引用失效时就减一。为零时,就认为可以被回收。但是这里存在一个问题就是对象的相互引用的时候,导致对象无法回收。
2.可达性分析:通过一系列的GC Roots来作为引用链的起点,如果没有任何的一个引用链相连的话,被视为可回收的对象
3.png
可以作为GC Roots的对象包括以下几种:
-
虚拟机栈中引用的对象
-
方法区中静态变量引用的对象
-
方法区中常量引用的对象
-
JNI引用的对象
可以看到可以作为Roots的是程序员在方法调用的时候直接操纵的对象,而不是包含在对象的引用指向的对象。 -
可以用弱引用和软引用来实现内存不足时对象回收问题。
可达性分析中的不可达对象也并不是马上死亡,它需要经历至少两次标记的过程。当对象没有和GC Roots相连的时候,进行第一次标记,并且进行一次筛选,如果覆盖了一个对象的finalize(),切没被系统掉用过,方法会将改对象放入F-Queue中等待,然后调用finalize()方法,注意这个方法只被系统调用一次,如果这个时候将对象赋值给一个引用,那么这个对象将会被“救活”,反之,进行第二次标记然后被回收。
- 方法区中的回收
方法区也就是永久代,主要回收对象是废弃常量和无用的类。废弃常量以常量池中的字面量为列:常量池中有“abc”的String类型的字符串,如果没有任何一个地方的字符引用为abc的话就被视为废弃常量。而无用的类的判断就复杂很多:
1、该类所有的实例对象都已经被回收,也就是内存中不存在该类的实例对象
2、该类的ClassLoader已经被回收
3、该类的Class对象没有被引用,没有在任何地方通过反射访问。
垃圾回收算法
- 标记-回收算法:效率低,容易产生大量的碎片
- 复制算法:使用一半的内存,当一块内存用完了,把这内存存活的对象复制到另一块上面,然后这块内存进行清除操作。
- 标记-整理:将存活的对象移动到一遍,以此为界限,清除边界以外的内存
- 分代收集算法:把堆内存分为新生代、老年代。这样就可以针对各个年代的特点采用适当的回收算法。新生代在垃圾回收每次有大量的对象死去,使用复制算法;老年代对象存活比较久,用标记-整理算法或者标记-清除算法。
在发生GC时,所有的线程都是中断的。所以在Android中发生内存抖动,频繁GC,会导致页面卡顿等等需要性能优化的地方。
网友评论