Ad removing finalize eventually (Re: JEP 411 Headaches: Instrumenting private methods in the JDK for authorization checkpoints.
Rony G. Flatscher
Rony.Flatscher at wu.ac.at
Mon Aug 2 18:39:15 UTC 2021
On 02.08.2021 17:27, Andrew Haley wrote:
> On 7/27/21 11:01 AM, Rony G. Flatscher wrote:
>> Background of the question: in an ooRexx-Java bridge for each Java object an ooRexx peer object gets
>> created and needs to exist as long as the Java object exists. Once the Java object gets garbage
>> collected the ooRexx peer object needs to be freed as well. The bridge between ooRexx (an
>> interpreted, message based, dynamically typed language) and Java is realized via JNI. Currently
>> (actually since 20 years) on the Java side the finalize method gets employed to signal to ooRexx
>> that its ooRexx peer object needs to be removed.
> One problem is that there's no guarantee that peers ever get removed until
> a Java program ends, and maybe not even then, so if you actually need that
> to happen finalizers are not what you need. And if you don't need cleanups
> to happen, you won't be affected.
> The "more flexible and efficient" ways to do it are ReferenceQueues, but
> they'll still suffer from the same problem.
The same is the case with ooRexx that it is not guaranteed that object's uninit-methods (if present)
run, although the interpreter does its best to run them once ooRexx objects are not referenced anymore.
An important use case for being able to become active at the time that objects (with bound
resources) are not referenced anymore are long running applications where resources should get freed
as soon as they are not needed anymore. This should work either way. Imagine e.g. a Java based web
server where scripts in ooRexx (or in any other language) are running, then it becomes important to
be able to release resources that are not needed anymore on either side.
E.g. the ooRexx-Java bridge when being used by Java via the Java scripting framework will create a
new ooRexx interpreter instance each time a new ScriptEngine gets created, serving as the peer for
the ScriptEngine (one could create dozens, even hundreds of such engines, and instrumentate them in
parallel, as long as enough resources are available). If the Java ScriptEngine goes out of scope at
the Java side its peer ooRexx interpreter instance should be terminated, the same is true for peer
objects for either side (Java peer objects for Rexx objects, i.e. Rexx objects being boxed in Java
proxy objects, and vice versa, ooRexx peer objects for Java objects such that one can send messages
to an ooRexx peer to the Java side where with reflection the appropriate methods get invoked in the
corresponding Java object).
In the meantime I have a test implementation based on the PhantomReference class (thanks to Peter to
point them out) which I will be using for testing different scenarios.
One observation (in this case on Java 8) is that if running System.runFinalization() the finalize
methods get excercised earlier (it seems at the point in time where objects are finalizable while
the runFinalization method executes) and more reliable than the PhantomReference objects showing up
on the reference queue (which they may or may not be the case depending on the test circumstances).
It would be desirable if finalizable objects (whether they have a finalize method or not) being
referred to by PhantomReferences would be put on the reference queue at the point in time
runFinalization() executes (in that case it may even make sense to keep runFinalization()).
More information about the jdk-dev