你去ibm的开发站点找一下,哪里有一篇讲垃圾收集机制的文章。不过对于你的问题,还是很容易想到解决的办法的,引用计数就可以。

解决方案 »

  1.   

    对象a引用对象b,对象b引用对象a?怎么引用?用代码举个例子。
      

  2.   

    A a=new A();
    B b=new B(a); //b refer to a
    a.refer(b); //a refer to b
      

  3.   

    http://www-900.ibm.com/developerWorks/cn/java/j-jtctips/part2/index.shtml#to上面看看
      

  4.   

    谢谢singh(冥王星) ,好文章,现转载。但是没有解决我的问题。Phil Vickers
    软件工程师,IBM Hursley Lab
    2002 年 1 月垃圾收集器(Garbage Collector(GC))是一直伴随着 Java 程序员的最有争议的问题之一。我们接受了独立的收集器的原则,但是控制该收集器的迫切需要常常被证明是不可抗拒的。典型情况下,您用好了一个或多个资源,并指望它们会被回收。但它们并没有被回收。一定出现了问题!IBM 为我们提供了一种强行执行 GC 的方法 — 调用 System.gc(),那么使用这一调用就一定没有问题,是这样吗? 错。几乎总是错的。GC 称为“内存管理器”会更好,因为这是它真正做的事情。同 C/C++ 一样,它根据应用程序的请求分配内存。但是与 C/C++ 不同的是,内存释放是 GC 单独执行的。因为内存管理的复杂性中 99% 与未使用内存的自动定位及释放有关。一般我们提到“GC”就是指 Java 内存管理。Java 虚拟机(Java virtual machine(JVM))有它自己的内存池。我们不使用一般的本地方法,如 malloc。当然,这个内存池只是从本机 OS 中分配的一大块。Java 内存被称作堆。当 Java 对象需要内存时,就从堆中进行内存分配。通常,JVM 在被要求时才对内存进行分配。当且仅当内存分配发生错误(内存溢出)时才执行 GC。是的,是的,我知道 Java 1.1.8 有“异步 GC”操作。在 IBM Java SDK 中,这个循环实际上从未被激活。因为性能的缘故,异步 GC 操作被配置成只有在您的应用程序确实什么事也不做的时候才会运行。即使您的应用程序静止,也要经过相当长时间的超时,异步 GC 才会运行。在 Java 2 中已经没有异步操作了。因此,对于 IBM Java SDK 来说,GC 完全是一个同步操作,而且仅在内存分配发生错误时才发生。GC 的工作方式
    我们当然不会完整地讨论这些内容;关于这一主题已经有整本专著问世了。我们只要讨论基础知识。GC 通过扫描 JVM 里运行的所有线程的堆栈和寄存器来执行。如果它发现有些东西似乎是对 Java 堆内的引用,GC 将会继续查下去。如果该引用确实是对对象的引用,那么 GC 将跟随该对象内的所有引用。被引用的对象以及该对象所引用的所有对象都将被“标记”(或标志)。显然,只有在线程被中止的情况下它才能起作用,因此,GC 要停止 JVM 里的所有线程才能开始执行,当然,其中不包括它正在其上运行的那个线程。标记阶段结束时,GC 会扫描堆,并对照在标记阶段标志的那些对象检查堆里的所有对象。任何没有被标记的对象都是没有被任何线程引用的对象,因而,这些对象将会被回收并被放回到空闲池。此处需要指出的重点是:GC 是一个停止一切的操作。
    GC 是一个同步操作。
    GC 需要扫描每个线程的堆栈。
    GC 需要扫描整个 Java 堆。
    就 CPU 使用和时间而言,GC 操作代价高昂。这就是我们要尽可能减少它的执行的原因。虽然它效率极高,但在一个有许多线程并且堆的大小达多兆字节的环境中运行需要时间。这解释了相当常见的说法 -“我的对象在应该被回收的时候并没有被回收”。它们符合被回收的条件;可是没有必要运行 GC,所以它并没有执行。System.gc()
    System.gc() 是“内存分配错误是运行 GC 的唯一原因”这一规则的一个例外。虽然这可能是一种例外情况,但并不是一个好主意。请相信我。文档说明该调用设置了一个标志,该标志表明在 JVM 非常想要时可以运行 GC。System.gc() 调用实际上做的事情是:如果调用它的时候有一个 GC 循环正在运行,那么就怱略这次调用;否则,就开始一次完整的 GC 循环。这就是说,每次(或 99.9% 次)调用 System.gc() 的时候,您都会开始一个完整的 GC 循环。也许根本没有必要运行 GC,但是您还是强行让它执行完整个标记/扫描过程。您完全可以把 System.gc() 看作是 System.StopEverythingForAWhile() 调用或 System.SlugMyPerfomance() 调用。对于这个调用,有一个可能的正当理由。因为如果没有这个调用,直到堆用完 GC 才会运行。如果您有一个千兆字节的堆,在 GC 清理全部垃圾时,您将遭到相当大的打击,然后您可能会考虑以固定间隔强行执行一个 GC 循环以达到“少量多次”的效果。但是,在这种情况下,您考虑调整堆的大小会更好些。我们为什么要强行执行 GC?
    到处散布 System.gc() 调用的诱惑非常大。在某一阶段,我们总是遇到“内存溢出”的问题,第一反应是认为 GC 出了问题,并强行执行一个循环。尽管这常常能改善局面(至少是暂时能),并且似乎验证了“GC 出了问题”这一想法,但事实也许并非如此。请记住,GC 处于食物链的底部。由于 GC 的常规操作是彻底检查系统运行时的状态,所以代码中其它地方所犯的错误常常会被 GC 暴露出来。这样,别处所犯的错误导致 GC 没有响应,而程序员认为 JVM 是在 GC 处异常结束的。因此,应该是 GC 的问题。追查要从定位问题开始,因此,我们强行让 GC 在代码中的不同地方执行。不幸的是,一旦了解了 GC 查出的问题的真相,我们总是会忘记删除所有那些 System.gc() 调用。在一天结束时,最终在您的代码中会有成十、成百或者上千个强行执行 GC 的调用(您有多少个呢?)。除了缓慢的性能和在强制执行的非必要 GC 循环上花费过多的时间之外,这使您一无所获。当允许 GC 按您预想的那样运行时,您可能会感到吃惊,一个劣等系统的响应速度也如此之快。
      

  5.   

    "当一个对象没有引用时"
    Not exactly.
    it is 当一个对象is unreachable from any stack of the threads.see:
    http://www.csdn.net/expert/topic/872/872622.xml?temp=.2360041
      

  6.   

    GC 是一个停止一切的操作。
    GC 是一个同步操作。
    GC 需要扫描每个线程的堆栈。
    GC 需要扫描整个 Java 堆。Simply wrong!
    most mordern gc algorithm do it incrementally or generationally.
      

  7.   

    不管几个对象互相引用,只要其不能被ROOT集的对象引用,那么它们都是GC的收集对象.
      

  8.   

    ajoo,又看见你了,真高兴。
    copying gc确实是一个好想法。但是深度拷贝是不是效率太低了呢?如果使用Thread引用计数,即每个stack保留对对象的引用计数不是更简单,更快呢?当某个对象不属于任何thread stack时既可回收。另外,请教一个singleton的问题。究竟一个VM保留一个Singleton还是一个container保持一个singleton?J2EE使用的context可否用singleton代替?另外,在讨论一下pattern的问题
    1。现在的pattern分类似乎以功能为标准,从结构上划分的话,有些pattern可归为一类.比如:state,strategy,command,又如:composite,decorator。
    相反,adapter倒有两种:内部和外部
    2.有些pattern太简单,似乎称不上pattern,比如template。有些他又不认为是pattern,比如state machine
    3.目前的pattern大多是一种类(如command,singleton)或两种类之间的关系
    (如factory生成对象,observable注册observer,visitable注册visotor),没有三种类之间的关系(比如MVC不认为是一种pattern,,而拆成两段,其实MVC是一种整体的概念)。所以,这里具有一个度的问题,GOF认为小粒度(比如继承,多态)的是基本概念,中粒度的是pattern,大粒度的是framework。其实,pattern的定义并没有指定其粒度,而是在某种环境下的一种解决方案。
      

  9.   

    there're variants in the algorithm that does the thing incrementally or generationally. So the deep copy is not done all at once.
    ref-counting suffers from cyclic reference. And it also at least doubles the cost of reference assignment and destruction. think how frequent reference assignment and destruction can be in our program!I believe that static singleton is per VM. But, you can make object-level singleton, which can be per container or per anything.
    Don't spend too much time on pattern's concept. It's just a natural result of thinking, and some good practice. I wouldn't think it's a shame if I don't know a pattern's name or meaning. Say, "so what?"
      

  10.   

    ajoo(聪明的一猪) 
    good answer.
    But could you poit out whether the J2EE context is a VM singleton.It seems not,since the factory in different J2EE container is different
      

  11.   

    我提出想要删掉几个pattern,听听大家的意见。
    1.template,因为太简单,与继承没有什么区别
    2.strategy,与command太象
    3.interpreter,因为太局限,否则为什么compiler-compiler(自动生成compiler的machine)不是pattern
    4.builder,其实就是对抽象对象设定属性1,属性2,属性3...,然后得到结果,能算pattern吗?另外,我建议提取一些软件工程的中粒度解决方案成为软件工程pattern和anti-pattern。这样,比起复杂面广的讨论RUP,XP,CMM更有意义。
    类似desogn pattern,software enginerring pattern(anti-pattern) 也要如下内容:
    1.名称,描述
    2.应用场合(context)
    3.优点,trade-off
    4.例子
    5.关联pattern.
    各位意下如何
      

  12.   

    sorry, I never did EJB development. so not qualified to say anything about it.
    But does it mean anything to find a pattern name for a thing?
      

  13.   

    of course not.It's only a word game.-:)