Lightweight finalization for the JDK without any drawbacks was: Why is finalize wrong?
Jaroslav Tulach
jaroslav.tulach at oracle.com
Fri Aug 8 08:45:08 UTC 2014
Roger Riggs wrote:
> I can't help but ask how this differs from sun.misc.Cleaner?
> One concern is about security and robustness of the code that is run on
> the system threads.
> I don't have the history but these are very sensitive areas of operation.
Thanks for bringing Cleaner into the picture, Roger! I was told something like
this exists in the implementation packages of JDK but I could not find it (was
looking for a class like Finalize.*Something.*...).
Yes, the active reference queue concept is quite similar to Cleaner. That has
a lot of positive implications, I think:
- NetBeans needs activeReferenceQueue(), JDK needs Cleaner - there must be a
need for this kind of lightweight finalization, then!
- JDK9 promises to be more secure by disallowing access to sun.* packages.
Together with such promise the team announced that some useful utilities will
be turned into official API (sun.misc.Unsafe particularly). Looks like Cleaner
is another useful tool as well - so let's treat my quest for lightweight
finalization as an attempt to come up with an official API to replace Cleaner.
Technically both activeReferenceQueue and Cleaner seem similar, except
following differences:
- Cleaner's run() method is called on internal JDK thread. If the client
cleanup code misbehaves, no References will be queued into their
ReferenceQueues. That is probably too fragile for public API. My patch which
introduces Reference.activeQueue() is doing client code callbacks on the
finalizer thread which already has all the sufferings with client code - e.g. no
increased security/stability risks. In the process of seeking official API for
lightweight finalization I suggest to use the finalizer thread for callbacks.
- Cleaner creates own instance of PhantomReference while activeQueue can be
used with any type of Reference (just choose your own and make it implement
Runnable). For many usecases the activeQueue approach is more efficient. Often
one needs WeakReference or SoftReference to the object and also the cleanup
code - with Cleaner current design this requires two references - one client
one and one internal PhantomReference in the Cleaner. activeQueue needs just
the client one. Even if one does not need own reference, the activeQueue
approach needs one object less - as the PhantomReference and Runnable are
merged into one.
In any case I am really glad a synergy in needs of JDK and NetBeans has been
found. Hopefully that will lead to easier acceptance of the need for a official
public API for lightweight finalization.
-jt
Dne St 6. srpna 2014 12:17:38, Jaroslav Tulach napsal(a):
> OK,
> time to show the code. I've added an alternative patch to JDK-8051843:
> https://bugs.openjdk.java.net/secure/attachment/21640/ActiveQueueFinalizer.d
> iff I suggest to start reading it from bottom - e.g. the test, the
> documentation and then the implementation.
>
> Now there is time for some discussion: First of all I should mention that
> the patch is sufficient to solve all the problems NetBeans and people
> reusing NetBeans libraries in dynamic classloader systems (e.g. containers)
> have. This is a pro.
>
> Next thing to check is whether the change can cause some harm. Here are the
>
> areas of concern we have identified so far:
> > > > # 1 - Because of automatic JDK management thread?
>
> The patch introduces no new thread. It reuses already existing one. No
> allocation of new system resources. Status quo is kept.
>
> On the other hand, this is a pro over own ReferenceQueue.remove calls. One
> saves a thread per instance of such queue.
>
> > > > # 2 - Or because once finalize() is called, one still has reference to
> > > > the
> > > > "gone" object and can re-activate it?
>
> This problem does not exist with activeQueue(). When the run() method on a
> Reference is called, this.get() already returns null. I believe this
> addresses
> also David M. LLoyd's concern:
> > Yup. Did you know that an object can be finalized while there are still
> > instance methods of that object executing? We've actually seen it
>
> Sure, but that cannot happen with activeQueue() as the referent is really
> gone before appropriate Reference.run() is executed.
>
> Certainly a pro over Object.finalize. Status quo with respect to
> ReferenceQueue as that behaves the same.
>
> > > > #3 - Or because the finalizer thread is shared between completely
> > > > unrelated
> > > > objects and misbehavior of one can cause problems for others?
>
> No regression in this aspect either. finalizer thread already has this
> problem, and we are not making it worse. Status quo is kept. Well written
> application actually benefit from this behavior, as they save system
> threads (compared to own ReferenceQueue.remove implementations).
>
> > If you still think that finalize is a good idea, given that it's
> > basically defective *and* there is almost always a better solution,
>
> I believe activeQueue() in core libraries is good idea. Because it fills the
> gap between (dangerous, unusable) Object.finalize and (ineffective)
> attempts to code the same logic in libraries (via own
> Thread+ReferenceQueue.remove)
>
> I see at least one pro and no cons. Are there other points of view?
> -jt
More information about the core-libs-dev
mailing list