为什么java没有确定性析构函数?

时间:2011-02-03 17:23:41

标签: java garbage-collection

我不明白为什么你不能在不改变语法的情况下拥有堆栈对象。如果有人引用了一个没有超出范围的对象,请标记GC的对象并且不要破坏它。如果不是这种情况,那么破坏它是完全合理的。

是否因为无论对象是否有引用,类本身的行为都不同?似乎可解决 - 如果对象有析构函数,如果有外部引用,则实例的运行时错误超出范围。

请帮助我理解。

5 个答案:

答案 0 :(得分:1)

通常的JVM实现不使用引用计数;因此,任何依赖引用计数的方案都会在典型的JVM上失败。它将符合向JVM添加引用计数,但是,这样的实现可能会慢得多。

我不清楚你在帖子中建议采用什么方法。如果你想以某种方式检测到对象的引用,很可能,即使是最琐碎的对象用法也会破坏你的检测,例如。

{
 A a = new A();
 a.m();
}

这有两个问题:

  • 读取局部变量a已经引用了对象(在评估堆栈上)。如果“制作引用”已被视为“不符合作为堆栈对象”,那么堆栈对象的方法将是不切实际的
  • 在对象上调用一个方法,该方法可能会引用内部的this,对调用者不可见。因此,即使您有一个允许访问包含堆栈对象的局部变量的策略,您也不能真正允许对堆栈对象进行方法调用。因为那将包括对finalize()的调用,拥有堆栈对象将毫无意义。

答案 1 :(得分:1)

因此,我可以理解的答案是以这种方式实现堆栈对象是可行的,但需要引用计数垃圾收集器。 Java(可能是.NET)已经避免了这条路线,因为:

  

您可以使用a来扩充引用计数   “真正的”GC,自然要运行   少见,因为只有一些(经常   小)生成的一部分垃圾   包含循环。另一个因素是   速度 - 一个聪明,优化的GC可以做到   比引用计数要好得多   特别是在线程存在的情况下   (增加/减少   由于这个原因,因此引用了更多的数据   锁定)

请参阅this answer to why-dont-most-jvm-gcs-use-refcounts

答案 2 :(得分:0)

  

为什么在不改变语法的情况下不能拥有堆栈对象。如果有人引用了   不超出范围的对象,   标记GC的对象,不要   破坏它。

除了对象是在堆栈之外,占用了下次方法调用可能需要的空间。

答案 3 :(得分:0)

最简单的答案是因为GC不会在每个对象删除时运行 - 它会定期运行 - 这就是为什么现在在JDK 7中添加try-with-resources后面的努力。

http://blogs.oracle.com/darcy/entry/project_coin_try_out_try

C ++解决了RAII的这个问题,即使使用GC框架,也有一个单独的堆栈创建对象概念。

答案 4 :(得分:0)

我认为这个要求会有问题:

  

如果object有析构函数,如果有外部引用,则实例的运行时错误超出范围。

因为这意味着你需要在声明类型具有析构函数的局部变量的任何方法返回时执行GC循环。

可能有效的东西类似于艾菲尔expanded variables。从扩展变量分配引用变量(包括方法参数)是非法的,因此不会发生此问题。