Java垃圾回收器

引用记数:一种简单但速度很慢的技术,每个对象都含有一个引用计数器,当引用连接值对象时,引用记数加1,;当引用离开作用域或被置为null时,引用记数减1,遍历所有对象,管理引用计数的开销不大,但这项开销在整个程序生命过程中持续发生。
缺陷在于如果对象之间存在循环引用,可能出现"对象应该被被回收,但引用记数不为0",定位交互引用的的对象组所需工作量极大。常用来说明垃圾收集的工作方式,未被应用于任何一种Java虚拟机中。

在一些更快的模式中,垃圾回收器并非基于引用计数技术,它们依据的思想是:对任何活的对象,一定能追踪到其存活的堆栈或静态存储区之中的引用,这种方式确保了你访问过的对象必须是活的。这就解决了"交互自引用的对象组"的问题,
在这种方式下,Java虚拟机将采用一种自适应的垃圾回收技术。
有一种做法名为"停止--复制",即先暂停程序运行,然后将左右存活的对象从当前堆复制到另一个堆,没有被复制的全是垃圾。当对象被复制到新堆,它们是一个挨着一个的,所以新堆保持紧凑排列。对于这种"复制回收器"而言,效率会降低,首先得有两个堆,维护比实际需要多一倍的时间,
其次在于复制,项目稳定后很少甚至不产生垃圾,尽管如此,复制回收器仍然将所有的内存自一处复制到另一处,这很浪费。为了避免这种浪费,一些Java虚拟机会进行检查:要是没有新垃圾产生,就会转换到另一种工作模式,称为"标记--清扫"。
"标记--清扫"的思路同样是从堆栈和 静态存储区出发,遍历所有的引用,进而找出所有存活的对象,当找到一个存活对象,就会给对象设一个标记,这个过程不会回收任何对象,只有当标记工作全部完成后,才会开始清理工作,没有标记的对象将被释放,不会发生任何重复动作。所以剩下的
堆空间是不连续的垃圾回收器通过重新整理剩下的对象得到连续的堆空间。
如果所有的对象都很稳定,垃圾回收器的相率降低的话,就切换到"标记--清扫"方式,虚拟机会跟踪"标记--清扫"的效果,如果堆空间出现很多碎片,就切换回"停止--复制"方式,这边是"自适应技术"。

[讨论]垃圾回收器机制--质疑Think in java

07-23

[b]程序员都知道“初始化”的重要性,但通常忘记清除的重要性。毕竟,谁需要来清除一个int 呢?但是对于rn库来说,用完后简单地“释放”一个对象并非总是安全的。当然,Java 可用垃圾收集器回收由不再使用的对rn象占据的内存。现在考虑一种非常特殊且不多见的情况。假定我们的对象分配了一个“特殊”内存区域,没rn有使用new。垃圾收集器只知道释放那些由new 分配的内存,所以不知道如何释放对象的“特殊”内存。为rn解决这个问题,Java 提供了一个名为finalize()的方法,可为我们的类定义它。[color=#FF0000]在理想情况下,它的工作原rn理应该是这样的:一旦垃圾收集器准备好释放对象占用的存储空间,它首先调用finalize(),而且只有在下rn一次垃圾收集过程中,才会真正回收对象的内存。所以如果使用finalize(),就可以在垃圾收集期间进行一rn些重要的清除或清扫工作。[/color][/b]rnrn上面这段文字是Think in java 4.3 清除:收尾和垃圾收集 一章中的第一段.rn主要是想看看大牛们对垃圾回收器的看法, 因此, 没有循证原版Think in java中是怎么样描述这个问题的.rn当然, 这个问题也可能是由于jdk的版本引起的误差, 因此, 题目只是想吸引大家进来看看...呵呵rnrn请注意红字标明的部分, 我们可以看出, 作者(或者是翻译的误差? 这里就这么用用吧, 呵呵)认为: 垃圾回收器在运行时, 会首先调用对象的finalize方法, 在下一次垃圾回收器运行时, 释放该对象的内存.rnrn[color=#993366]为了照顾各位的情绪, 我还是把问题先在这里描述一下吧, 测试代码在Garbage类中的两个System.gc()的位置, 那里也有些注释的.rn * 我对jdk6.0_update_10的GC的运行机制的推测.rn * 1. 收集需要回收的对象, 并以某种方式记录下来.rn * 2. 调用上次记录在案的需要回收的对象的finalize方法.rn * 3. 回收已经调用过finalize方法的需要回收的对象.rn * 4. 将已经释放的对象从那个"记录"中移除.rn * 下一次运行, 继续1-4的步骤.[/color]rnrn我下面引入程序代码(基本上是Think in java中的源代码, 对其中有些东西做了一点小的调整, 效果比较明显一点.):rn1. Chair类, 我们就是用它来模拟垃圾的.rn[code=Java]rnpackage selfimpr.ThinkInJava.gc;rnrnpublic class Chair rn static boolean gcrun = false;rn static boolean f = false;rn static int created = 0;rn static int finalized = 0;rn int i;rn Chair() rn i = ++created;rn if(created == 35000)rn System.out.println("Created 35000");rn rn protected void finalize() rn //检测gc的第一次运行,gc第一次运行时调用finalize方法会触发并输出rn if(!gcrun) rn gcrun = true;rn System.out.println("Beginning to finalize after " +rn created + " Chairs have been ced. ");rn rn //监测收集编号i值为35000的Chair对象.rn if(i==35000) rn System.out.println("Finalizing Chair #35000, " + "i" + i + " " + created +rn "Setting flag to stop Chair creation");rn //当i值为35000的Chair的对象被垃圾收集后, 将f设置为true, 结束创建.rn f = true;rn rn //记录销毁对象的数目rn finalized ++;rn if(finalized >= created-100) rn System.out.println("All " + finalized + " finalized");rn rnrnrn[/code]rn2. 主类, 控制程序监测GC运行rn[code=Java]rnpackage selfimpr.ThinkInJava.gc;rnrnpublic class Garbage rnrn public static void main(String[] args) rn if(args.length == 0) rn System.err.println("Usage: \n" +rn "java Garbage before\n or:\n" +rn "java Garbage after");rn return ;rn rn //1. Chair.f为假时不断的创建Chair和String对象.rn while(!Chair.f) rn new Chair();rn new String("To take up space");rn rn //结束创建活动后, 打印总共被创建了多少Chair对象.rn //在这个过程中, JVM自动运行的垃圾回收回收了多少个Chair对象.rn System.out.println("After all Chairs have been created:\n" +rn "total created = " + Chair.created + rn ", total finalized = " + Chair.finalized);rn if(args[0].equals("before")) rn System.out.println("gc():");rn System.gc();rn System.out.println("runFinalization():");rn System.runFinalization();rn rn //这个地方进行了改动, 下面这两行代码是新加的.rn //这里我做了两次测试rn /*rn * 第一次, 调用一次System.gc();rn * 第二次, 调用两次System.gc();rn * 然而, 和Think in java的讲法不同, 我调用第一System.gc()的时候, rn * 程序中没有释放的其他对象的finalize方法并没有被调用.rn * 而我调用两次System.gc();所有没有被释放的对象的finalize方法都被调用了.rn * rn * 因此, 感觉至少在jdk6.0_update_10中, GC的运行是在第二次的时候,rn * 才调用finalize方法并释放内存的.rn */rn System.gc();rn System.gc();rn rn //被改动的代码结束rn rn System.out.println("bye!");rn if(args[0].equals("after"))rn System.runFinalizersOnExit(true);rn rnrnrnrn[/code]

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试

关闭