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! > > >