finalize() *much* better than PhantomReferences (Re: Ad removing finalize eventually (Re: JEP 411 Headaches: Instrumenting private methods in the JDK for authorization checkpoints.

Hans Boehm hboehm at
Thu Aug 5 01:11:54 UTC 2021

One complication with bare PhantomReferences (as opposed to e.g. Cleaners)
is that you need to make sure that the Reference itself is kept reachable,
by putting it in some reachable data structure. As the spec says: "If a
registered reference becomes unreachable itself, then it will never be
enqueued." Normally the ReferenceQueue processing code will need to remove
it from that data structure. There's typically a fair amount of boilerplate
involved in correct use.

I think this can be unexpected for users. Could that be causing the problem


On Wed, Aug 4, 2021 at 5:59 PM Kim Barrett <kim.barrett at> wrote:

> > On Aug 4, 2021, at 2:54 PM, Rony G. Flatscher <Rony.Flatscher at>
> wrote:
> >
> > On 04.08.2021 16:35, Rony G. Flatscher wrote:
> >> Just for the record: the observed behavior (finalize() of all
> unreferenced objects runs at
> >> runFinalization() time, PhantomReferences are not put on the queue at
> that time) is the same for
> >> Java 6, 8, 11 and 16.
> >
> > O.K. now having implemented PhantomReferences to replace the usage of
> finalize() in the bridge it
> > turns out that finalize() gets invoked "magnitudes" of times (100 and
> more finazable objects in
> > different gc runs within a total run of five seconds) more often than
> their PhantomReferences are
> > being put on the reference queue (not a single one!) to allow to carry
> out the necessary finalizations!
> >
> > This is without employing runFinalization(), just the normal garbage
> collection that takes place in
> > a running system. (These tests were run against unit tests of the
> ooRexx-Java bridge to make sure
> > that the tests work the same as before the code changes.)
> >
> > ---
> >
> > Another test with JavaFX (the quite famous JavaFX address book example
> implemented in ooRexx) is
> > even interactively demonstrative: there were about ten, twelve
> finalize() runs while operating it
> > compared to not a single (!) reference being put on the reference queue
> in the same time frame!
> > Observing this one would wonder whether PhantomReferences would work at
> all (the implementation
> > works, it got tested separately).
> >
> > [To be able to compare the behavior I left finalize() in place but only
> output a debug message with
> > a string-id while for the same objects PhantomReferences got created and
> any such reference removed
> > from the reference queue would create a debug message there with the
> string-id as well and run the
> > cleanup method, however this has never happened.]
> >
> > ---
> >
> > So seriously, please consider to have PhantomReferences being serviced
> by the gc like finalizable()
> > objects, such that gc runs put PhantomReferences on the reference queue
> as early as possible.
> Finalization and PhantomReferences are implemented *identically* as far as
> detection and enqueuing, other than the criteria the GC uses for detection.
> It's almost all shared code, and that's been true for a long time (possibly
> forever, but I don't have easy access to really old versions of the code).
> So I think there is a bug in the testing. My guess would be that the
> referents of the PhantomReferences aren’t actually phantom reachable. Not
> having any knowledge of the code involved, I can’t even speculate on why
> that might be. But I have no other explanation to offer.

More information about the jdk-dev mailing list