Index: jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/TransientFileFactory.java =================================================================== --- jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/TransientFileFactory.java (revision 795481) +++ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/TransientFileFactory.java (working copy) @@ -45,18 +45,19 @@ * Queue where MoribundFileReference instances will be enqueued * once the associated target File objects have been gc'ed. */ - private ReferenceQueue phantomRefQueue = new ReferenceQueue(); + private final ReferenceQueue phantomRefQueue = new ReferenceQueue(); /** * Collection of MoribundFileReference instances currently * being tracked. */ - private Collection trackedRefs = Collections.synchronizedList(new ArrayList()); + private final Collection trackedRefs = + Collections.synchronizedList(new ArrayList()); /** * The reaper thread responsible for removing files awaiting deletion */ - private final Thread reaper; + private final ReaperThread reaper; /** * Shutdown hook which removes all files awaiting deletion @@ -149,9 +150,8 @@ // to avoid ConcurrentModificationException (JCR-549) // @see java.lang.util.Collections.synchronizedList(java.util.List) synchronized(trackedRefs) { - for (Iterator it = trackedRefs.iterator(); it.hasNext();) { - MoribundFileReference fileRef = (MoribundFileReference) it.next(); - fileRef.delete(); + for (Iterator it = trackedRefs.iterator(); it.hasNext();) { + it.next().delete(); } } @@ -163,7 +163,9 @@ // jvm shutdown sequence has already begun, // silently ignore... } + shutdownHook = null; } + reaper.stopWorking(); } //--------------------------------------------------------< inner classes > @@ -172,6 +174,8 @@ */ private class ReaperThread extends Thread { + private volatile boolean stopping = false; + ReaperThread(String name) { super(name); } @@ -181,11 +185,15 @@ * marker objects are reclaimed by the garbage collector. */ public void run() { - while (true) { + while (!stopping) { MoribundFileReference fileRef = null; try { // wait until a MoribundFileReference is ready for deletion fileRef = (MoribundFileReference) phantomRefQueue.remove(); + } catch (InterruptedException e) { + if (stopping) { + break; + } } catch (Exception e) { // silently ignore... continue; @@ -196,17 +204,25 @@ trackedRefs.remove(fileRef); } } + + /** + * Stops the reaper thread. + */ + public void stopWorking() { + stopping = true; + interrupt(); + } } /** * Tracker object for a file pending deletion. */ - private class MoribundFileReference extends PhantomReference { + private class MoribundFileReference extends PhantomReference { /** * The full path to the file being tracked. */ - private String path; + private final String path; /** * Constructs an instance of this class from the supplied parameters. @@ -214,7 +230,7 @@ * @param file The file to be tracked. * @param queue The queue on to which the tracker will be pushed. */ - MoribundFileReference(File file, ReferenceQueue queue) { + MoribundFileReference(File file, ReferenceQueue queue) { super(file, queue); this.path = file.getPath(); } Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/DatabaseJournal.java =================================================================== --- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/DatabaseJournal.java (revision 795481) +++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/DatabaseJournal.java (working copy) @@ -227,6 +227,8 @@ janitorNextRun.set(Calendar.MILLISECOND, 0); } + private Thread janitorThread; + /** * The instance that manages the local revision. */ @@ -376,9 +378,9 @@ // Start the clean-up thread if necessary. if (janitorEnabled) { - Thread t1 = new Thread(new RevisionTableJanitor(), "ClusterRevisionJanitor"); - t1.setDaemon(true); - t1.start(); + janitorThread = new Thread(new RevisionTableJanitor(), "Jackrabbit-ClusterRevisionJanitor"); + janitorThread.setDaemon(true); + janitorThread.start(); log.info("Cluster revision janitor thread started; first run scheduled at " + janitorNextRun.getTime()); } else { log.info("Cluster revision janitor thread not started"); @@ -586,6 +588,9 @@ */ public void close() { close(false); + if (janitorThread != null) { + janitorThread.interrupt(); + } } /**