Solar wrote:
Or, to put it differently: I'd employ a C++-coder-gone-Java without any hesitation. I would interview a Java-coder-gone-C++ very closely before allowing him to work in my project.
I absolutely agree. My company's recruiting process is set up specifically to avoid this problem.
Pype.Clicker wrote:
Iigc, the case Solar was talking about implies that A is a static object handling the GUI. It doesn't necessarily needs to be native.
Just let's suppose that upon Gui.RegisterEvent(Gui.MouseMovedEvent, B); the static object GUI adds B (or more likely, an EventHandlerObject referencing B) into a HashTable so that it can retrieve who's interested into MouseMoved event later ...
If you now remove all references to B in your program but forget to call Gui.UnregisterEvents(B) before this, then there's a dangling reference to B in the GUI's hashtable (making B never collected), even if the window that contains B has been released an is now inactive...
The natural place where I would have called UnregisterEvents(this) would have the destructor of B (that is, if B gets out of scope, unregister everything related to B)... which would fail to work with a GC, of course.
Ahh... I get it now. This is actually "unintentional object retention", not a memory leak per se. The problem is caused by the Gui's scope -- it is a long-lived object referring to short-lived objects.
The solution to this would be for Gui to use weak references to event handlers instead of strong references. That way, Gui's reference to B doesn't prevent B from being garbage collected. Whenever the event occurs, Gui would check its weak reference to B to see if it's still valid. If so, the event is delivered; if not, it is safe for Gui to remove B from its hashtable. In this case, the designers of Gui must have their thinking caps on.
Solar wrote:
Finalizers in Java are not fairly evil, they are evil.
Heh, ok. I was being charitable for cases like Pype's (although in truth Pype, writing to a log file in a finalizer scares the willies out of me...)
Quote:
And as for performance... every Java [tt]Object[/tt] does have a finalize() function, which simply returns while doing nothing. One more function call to execute for each object finalized. (Compare this with a C++ object only having native member types - "destruction" is a nop in this case.)
My teammate and I were just dealing with this issue yesterday (we're doing a lot of Java/C++ integration via the JNI this week). Even though every Java object inherits "finalize()" from java.lang.Object, only those objects that actually override finalize() are put on the finalization queue by the GC. The performance would just be too terrible otherwise.