Hi Jaroslav, In my opinion the greatest downside of the finalize() is that involves enlisting in a shared queue prior to the object creation. The queue is shared amongst the entire VM and that could be a potential bottleneck. In practical terms having a finalize method involves a full memory fence when a new instance is created (or cloned) and removing a finalize() method can break some racy code.
Like David Lloyd mentioned finalize() can be invoked concurrently to some methods (if there is no reachability to 'this'). OTOH I see finalize useful for managing native resources mostly and possibly stopping (signaling) threads left unmanaged. In that particular case synchronization is a must, so it comes naturally. Personally I never use dedicated threads with ReferenceQueue but I poll (expunge) the queue on add/put. If the there are too many successful ReferenceQueue.poll() hijacking the Finalizer thread is an option. Something among the lines: public static interface Cleaner<T, Ref extends Reference<? extends T>>{ void clean(Ref ref); } public static <T, Ref extends Reference<? extends T>> void expunge(Cleaner<T, Ref> cleaner, final ReferenceQueue<T> queue, int expungeThreshold){ Reference<? extends T> w=queue.poll(); if (w==null) return;//keep the method short, so it's inlined; queue being empty is the fast lane expungeImpl(cleaner, w, queue, expungeThreshold); } static <T, Ref extends Reference<? extends T>> void expungeImpl(final Cleaner<T, Ref> cleaner, Reference<? extends T> ref, final ReferenceQueue<T> queue, int expungeThreshold){ expunge(cleaner, ref); for (;--expungeThreshold>0 && null!=(ref=queue.poll());){ expunge(cleaner, ref); } if (expungeThreshold==0){//delegate a full expunge to the finalizer //the anon. class stores cleaner and queue in fields, and the c-tor has happens before with finalize() unlike any other method new Object(){//feel free to extend/wrap WeakRefence(cleaner) and also keep weak ref to queue useful for non-native resources protected void finalize(){//keep in mind: the execution of cleaner.clean(Ref) will not have the right ContextClassLoader, ThreadGroup, AccessControlContext expunge(cleaner, queue, Integer.MAX_VALUE); } }; } } @SuppressWarnings("unchecked") private static <T, Ref extends Reference<? extends T>> void expunge(Cleaner<T, Ref> cleaner, Reference<? extends T> ref){ cleaner.clean((Ref) ref); } Some colorization: http://pastebin.com/1V9Jhavz Of course the finalize method is not guaranteed to execute at all but if expungeThreshold is greater than 1 and expunge is called on each add/put operation, still it should be ok. Cheers Stanimir On Mon, Aug 4, 2014 at 4:46 PM, Jaroslav Tulach <jaroslav.tul...@oracle.com> wrote: > Hi. > Last week we touched topic of finalization and what is wrong with it. I > proposed three > reasons why Object.finalize is bad. Is it correct and extensive list or > would you change > it or expand it? Thanks as ... > > > > # 1 - Because of automatic JDK management thread? > > > # 2 - Or because once finalize() is called, one still has reference to > the > > > "gone" object and can re-activate it? > > > #3 - Or because the finalizer thread is shared between completely > > > unrelated > > > objects and misbehavior of one can cause problems for others? > > ...I consider #2 the worst idea: > > > > My personal top three starts with #2. That is logically invalid. #3 > can be > > > a problem, but so can be any other misbehaving thread in an > application. > > > #1 is completely OK, from my perspective > > and I think I got some support... > > > Weak references and reference queues were introduced to address some of > > the short comings of finalization as well as providing other > > capabilities within a GC'd environment. > > ...I just have to say that the Reference&ReferenceQueue as of JDK8 is not > enough. As > the case of activeReferenceQueue shows, the fact that each instance of > ReferenceQueue where one uses remove() needs one dedicated thread is a big > flaw. > Fixing the flaw in an external library is not easy (see the summary from > last week: > > https://bugs.openjdk.java.net/browse/JDK-8051843?focusedCommentId=13531670&p > [1]age=com.atlassian.jira.plugin.system.issuetabpanels:comment- > tabpanel#comment-13531670). > > Moreover David Holmes finds introductions of new system level threads > uneasy: > > > The threading aspect is somewhat tangential. Any time you choose to > > introduce a new thread to perform a task you have to be concerned about > > the lifetime of the task and thus the thread. > > But when thinking about it, we can have functionality of > activeReferenceQueue in JDK > without introducing any new thread! We can reuse the existing finalizer > one! > > I plan to propose a patch which will look at the activeReferenceQueue > problem from a > completely new perspective and offer "lightweight finalize" solution that > will have > above discussed properties #1 and #3, but will not suffer from #2 (the > biggest > problem with Object.finalize). > > I just wanted to ask before I start: Is somebody aware of other problems > with > Object.finalize than #1, #2 and #3? > -jt > > > > -------- > [1] > > https://bugs.openjdk.java.net/browse/JDK-8051843?focusedCommentId=13531670&p >