java内存的垃圾收集机制

来源:互联网 发布:java守护线程的作用 编辑:程序博客网 时间:2024/05/18 02:36

堆内存的垃圾收集
1、首先,堆里面存放的是java的对象实例,垃圾收集器不能随意的收集垃圾,必须先对堆内存中的对象进行判断,判断其是否还会被用到。
以下引自《深入理解JAVA虚拟机》

比较常见的判断方法是:给对象中添加一个引用计数器,每当有一个地方引用时,计数器值就加1;引用失效,计数器减一,任何时刻计数器为0的对象就不可能再被引用。
该算法较为简单,判断效率也高,但是缺点是很难解决对象之间相互循环引用的问题。比如,有两个对象已经不再被使用,但是这两个对象是互相引用的,那么它们的引用计数都不为0,GC收集器就不会回收它们。
所以主流的java虚拟机使用的都是可达性分析算法:通过一系列的“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径成为引用链,当一个对象到GC Roots没有任何引用链的时候(即从GC Roots到这个对象是不可达的),则该对象不可用。
GC Roots包括以下几种:
1、虚拟机栈中引用的对象
2、方法区中类静态属性引用的对象
3、方法去中常量应用的对象
4、本地方法栈中JNI引用的对象

2、其次,在可达性分析算法中不可达的对象也不是一定会被回收的

  • 对于不可达对象,会进行一次筛选,判断该对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法或者finalize方法已经被虚拟机调用过(对于任何给定对象,Java 虚拟机最多只调用一次 finalize 方法),都视为没有必要回收
  • 若该不可达对象被判定为有必要执行finalize()方法,那么这个对象会被一个由虚拟机自动创建的、低优先级的Finalizer线程回收。

方法区的垃圾收集:
  |–判断常量是否被弃用:没有任何对象引用常量池中的常量
  |–判断类是否被弃用:
   1、java堆中是否已经不存在该类的实例
   2、加载该类的ClassLoader已经被回收
   3、该类对象的java.lang.class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。


垃圾收集算法:
  

  • 标记-清除算法:首先标记出所有要回收的对象,然后统一回收这些对象。不足之处:1、效率低。2、产生大量的不连续的内存碎片,导致当有大对象需要分配内存时,无法找到足够而连续的空间,这样就会再一次触发垃圾收集动作。
  • 复制算法:将可用内存按容量划分为大小相等的两块,每次只是用其中一块。当这一块的内存用完了,就将还存活的对象复制到另外一块上面,然后把已使用过的内存空间一次清理掉。不足:代价是将内存缩小了一半。
  • 标记-整理算法:首先标记出所有要回收的对象,然后让所有存货的对象都向一端移动,然后直接清理掉端边界以外的内存。
  • 分代收集算法:当前商业虚拟机的垃圾收集都采用“分代收集算法”,根据对象存货周期的不同将内存划分为几块(新生代和老年代),然后根据各个年代的特点采用最适当的收集算法。新生代每次只有少量对象存货,就采用复制算法;老年代对象存活率高、没有额外空间,那么就采用“标记-清理”或“标记-整理”算法。
0 0
原创粉丝点击