Formatting came through poorly.  Please see [1]

- Bob

[1] https://gist.github.com/bobpaulin/ce6a83e45cd6bbf34051935324f10c63

On 2025/03/18 14:40:19 Bob Paulin wrote:
> Hi
> 
> In both cases it appears that finalize is being used as resource clean 
> up following the object being de-referenced.  In both cases finalize is 
> not the primary means of cleanup but rather a fall-through for 
> exceptional cases where processing is interrupted.  The consequences are 
> different in each case in the case of AbstractCacheServer the 
> cacheServer resource is not released which is a memory concern. In the 
> case of StandardProcessSession it's a call to rollback which is 
> important for data integrity. So I'm not sure removal is without 
> consequences but more so for StandardProcessSession.  I also agree that 
> implementing closeable might not be possible in all cases for 
> StandardProcessSession.
> 
> Cleaner looks like the simplest approach given it's wrapping some of the 
> complexity in working with the ReferenceQueue[1].  There are more 
> sophisticated things we could do using the ReferenceQueue directly (see 
> [2]).  There are some important caveats to implementing this that would 
> need to be followed to ensure it works.  First we can't use references 
> to the object AbstractCacheServer or StandardProcessSession within the 
> runnable or it will not trigger (since that would create a reference 
> thus it would not be Phantom).  It may be valuable to create a static 
> method on each of these classes that requires the constructor objects to 
> be passed to it in order to discourage the usage references to the 
> object.  Second we'll want to avoid passing "this.varaibles" to the 
> static method. Below is some example code for reference.  Notice what 
> happens if you try to pass this.value instead of value.  The cleaner is 
> not called because it's not a phantom ref anymore. So I'm not sure it's 
> required to pass the cleaning function to an additional class (as 
> demonstrated below) but it might help keep things cleaner and further 
> avoid references to the object that we're cleaning from.  Hope this is 
> helpful.
> 
> packagecom.bobpaulin.nifi;
> 
> importjava.lang.ref.Cleaner;
> 
> importjava.lang.ref.PhantomReference;
> 
> importjava.lang.ref.ReferenceQueue;
> 
> importorg.slf4j.Logger;
> 
> importorg.slf4j.LoggerFactory;
> 
> publicclassCleanerExample {
> 
> privatestaticfinalLogger LOGGER= 
> LoggerFactory.getLogger(CleanerExample.class);
> 
> //Static class just for demo purposes
> 
> publicstaticclassStandardProcessorSession {
> 
> privatestaticfinalCleaner cleaner= Cleaner.create();
> 
> privatefinalCleaner.Cleanable cleanable;
> 
> privatefinalString value;
> 
> publicStandardProcessorSession(finalString value) {
> 
> this.value= value;
> 
> finalRunnable cleanUpRunner= () -> rollback(value);
> 
> this.cleanable= cleaner.register(this, cleanUpRunner);
> 
> }
> 
> publicstaticvoidrollback(finalString value) {
> 
> System.out.println("Rollback Called. Value is "+ value);
> 
> }
> 
> }
> 
> publicstaticvoidmain(finalString[] args) {
> 
> StandardProcessorSession processSession= 
> newStandardProcessorSession("Hello");
> 
> //Needed for testing
> 
> finalReferenceQueue<StandardProcessorSession> refQueue= 
> newReferenceQueue<>();
> 
> // Create a phantom reference artificially
> 
> finalPhantomReference<StandardProcessorSession> helloPhantomReference= 
> newPhantomReference<>(
> 
> processSession, refQueue);
> 
> newThread(() -> {
> 
> LOGGER.info("Starting ReferenceQueue consumer thread.");
> 
> booleanreferenceNotFound= true;
> 
> while(referenceNotFound) {
> 
> try{
> 
> @SuppressWarnings("unchecked")
> 
> finalPhantomReference<StandardProcessorSession> reference= 
> (PhantomReference<StandardProcessorSession>) refQueue
> 
> .remove();
> 
> referenceNotFound= false;
> 
> LOGGER.info("Finalized has been finalized.");
> 
> } catch(finalInterruptedException e) {
> 
> // Just for the purpose of this example.
> 
> break;
> 
> }
> 
> }
> 
> LOGGER.info("Finished ReferenceQueue consumer thread.");
> 
> }).start();
> 
> // Lose the strong reference to the object.
> 
> processSession= null;
> 
> // Attempt to trigger a GC.
> 
> System.gc();
> 
> }
> 
> }
> 
> 
> - Bob
> [1] https://inside.java/2022/05/25/clean-cleaner/
> [2] 
> https://unitstep.net/blog/2018/03/10/java-phantomreferences-a-better-choice-than-finalize/
> 
> On 3/17/2025 4:11 PM, Dan S wrote:
> > I am currently working on NIFI-14340
> > <https://issues.apache.org/jira/browse/NIFI-14340> trying to replace the
> > overridden methods finalize in both AbstractCacheServer and
> > StandardProcessSession as
> > per the javadocs
> > <https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Object.html#finalize()>
> > finalize
> > is deprecated for removal.
> >
> > So my first question is whether we would like a replacement for these
> > finalize methods or is the solution for this ticket is as simple as just
> > removing them?
> > If we would like to replace them based on the suggestions given in JEP 421
> > <https://openjdk.org/jeps/421> then I have a few other questions.
> > The first suggested solution is to make the class implement
> > java.lang.AutoCloseable and then instantiate and use it in a try with
> > resources statement within a single lexical scope.
> > It does not seem to me that is plausible for AbstractCacheServer which is a
> > controller service and from what I understand is not used within a single
> > lexical scope.
> > It also does not seem this would work for StandardProcessSession as there
> > are cases where instances of ProcessSession handle transferring flow
> > file(s) and commits in a catch block. If used
> > in a try resources it would be closed before the catch block code is called.
> > The second suggestion is to use Cleaners but that also seems difficult as
> > it seems from what I have read the right way to implement this would be
> > passing AbstractCacheServer and StandardProcessSession into a different
> > class to handle cleaning. I am not sure how that would be done for these
> > classes.
> >
> > Can I please get guidance on how we should proceed regarding these finalize
> > methods? Thank you!
> >
> 

Reply via email to