From d2ffb165d4f873fb71bb357d906f978b8c20ed27 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 3 Jul 2024 11:52:15 +0200 Subject: [PATCH] Added explanation of Cleaner lifecycle --- src/com/sun/jna/internal/Cleaner.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/com/sun/jna/internal/Cleaner.java b/src/com/sun/jna/internal/Cleaner.java index a164e9b5b..e80b59ae4 100644 --- a/src/com/sun/jna/internal/Cleaner.java +++ b/src/com/sun/jna/internal/Cleaner.java @@ -129,6 +129,17 @@ private static synchronized boolean deleteIfEmpty(MasterCleaner caller) { return caller.cleaners.isEmpty(); } + /* The lifecycle of a Cleaner instance consists of three phases: + * 1. New instances are contained in Cleaner.INSTANCES and added to a MasterCleaner.cleaners set. + * 2. At some point, the master cleaner takes control of the instance by removing it + * from Cleaner.INSTANCES and MasterCleaner.cleaners, and then adding it to its + * referencedCleaners and watchedCleaners sets. Note that while it is no longer + * in Cleaner.INSTANCES, a thread may still be holding a reference to it. + * 3. Possibly some time later, the last reference to the cleaner instance is dropped and + * it is GC'd. It is then also removed from referencedCleaners but remains in watchedCleaners. + * 4. The master cleaner continues to monitor the watchedCleaners until they are empty and no + * longer referenced. At that point they are also removed from watchedCleaners. + */ final Set cleaners = Collections.synchronizedSet(new HashSet<>()); final Set referencedCleaners = new HashSet<>(); final Set watchedCleaners = new HashSet<>();