why doesn't java have deterministic destructors?
I don't understand why you can't have stack objects without changing syntax. If anyone makes a reference to an object tha开发者_如何学JAVAt doesn't go out of scope, flag the object for GC and don't destruct it. If this isn't the case, its perfectly reasonable to destruct it.
Is it because then the class itself behaves differently whether or not the object has references? Seems solvable -- if object has a destructor, its a runtime error for an instance to go out of scope if there are external references.
Please help me understand.
The usual JVM implementation doesn't use reference counting; therefore, any scheme that relies on reference counting would fail on the typical JVM. It would be conforming to add reference counting to the JVM, however, such an implementation would likely be much slower.
It's not clear to me what approach you suggest in your posting. If you want somehow detect that a reference is made to an object, most likely, even the most trivial object usages would break your detection, e.g.
{
A a = new A();
a.m();
}
This has two problematic issues:
- Reading the local variable a already makes a reference to the object (on the evaluation stack). If "making a reference" is already considered as "not eligible as a stack object", then the approach of stack objects would be impractical
- A method is called on the object, which, in turn, might make a reference to
this
inside, invisible to the caller. So even if you have a policy that somehow allows access to local variables containing stack objects, you can't really allow method calls for stack objects. As that would include the call tofinalize()
, having stack object would be fairly pointless.
So the answer as far as I can grasp is that implementing stack objects is feasible in this manner, but requires a reference counting garbage collector. Java (and presumably .NET) have avoided this route because:
You can augment refcounting with a "real" GC, which naturally has to run less often because only some (often small) part of the garbage generated contains cycles. Another factor is speed - a clever, optimized GC can do much better than refcounting, in particular in the presence of threads (which make incrementing/decrementing the refcounts much more costy, due to locking)
See this answer to why-dont-most-jvm-gcs-use-refcounts
why you can't have stack objects without changing syntax. If anyone makes a reference to an object that doesn't go out of scope, flag the object for GC and don't destruct it.
Except the object is on the stack, taking up space that you might need for your very next method call.
I think this requirement would be problematic:
if object has a destructor, its a runtime error for an instance to go out of scope if there are external references.
because it means you would need to do a GC cycle on return from any method that declared a local variable whose type has a destructor.
What might work is something similar to Eiffel's expanded variables. It is illegal to assign to a reference variable (including a method parameter) from an expanded variable, so this problem cannot occur.
Simplest answer is because GC isn't run at every object deletion - it's run periodically - and it's why there's effort now behind the try-with-resources additions to JDK 7.
http://blogs.oracle.com/darcy/entry/project_coin_try_out_try
C++ gets around this issue for RAII, even with GC frameworks, by having a separate notion of stack-created objects.
精彩评论