All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.crypto.util.dispose.DisposalDaemon Maven / Gradle / Ivy

Go to download

The FIPS 140-2 Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms certified to FIPS 140-2 level 1. This jar contains the debug version JCE provider and low-level API for the BC-FJA version 1.0.2.3, FIPS Certificate #3514. Please note the debug jar is not certified.

There is a newer version: 2.0.0
Show newest version
package org.bouncycastle.crypto.util.dispose;

import org.bouncycastle.util.Properties;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;

public class DisposalDaemon
        implements Runnable
{
    private static final Logger LOG = Logger.getLogger(DisposalDaemon.class.getName());

    private static ReferenceQueue referenceQueue = new ReferenceQueue();

    private static Set refs = Collections.synchronizedSet(new HashSet());

    private static final ScheduledExecutorService cleanupExecutor;

    private static final DisposalDaemon disposalDaemon = new DisposalDaemon();
    private static final Thread disposalThread;
    private static final long cleanupDelay;
    private static final String CLEANUP_DELAY_PROP = "org.bouncycastle.native.cleanup_delay";
    static
    {
        cleanupDelay = Properties.asInteger(CLEANUP_DELAY_PROP,5);

        //
        // Clean up executor accepts references that are no longer needed
        // and disposes of them in turn.
        //
        cleanupExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory()
        {
            @Override
            public Thread newThread(Runnable r)
            {
                Thread t  = new Thread(r,"BC Cleanup Executor");
                t.setDaemon(true);
                return t;
            }
        });

        //
        // Sets up the daemon thread that deals with items on the reference
        // queue that the GC has flagged as no longer needed.
        //
        disposalThread = new Thread(disposalDaemon, "BC Disposal Daemon");
        disposalThread.setDaemon(true);
        disposalThread.start();

        addShutdownHook();
    }

    private static void addShutdownHook()
    {
        //
        // On shutdown clean up the reference queue.
        //
        Runtime.getRuntime().addShutdownHook(new Thread()
        {
            @Override
            public void run()
            {
                ReferenceWrapperWithDisposerRunnable item = (ReferenceWrapperWithDisposerRunnable) referenceQueue.poll();
                while (item != null)
                {
                    refs.remove(item);
                    item.dispose();
                    item = (ReferenceWrapperWithDisposerRunnable) referenceQueue.poll();
                }

            }
        });
    }

    public static void addDisposable(Disposable disposable)
    {
        ReferenceWrapperWithDisposerRunnable ref = new ReferenceWrapperWithDisposerRunnable(disposable, referenceQueue);
        refs.add(ref);
    }

    public void run()
    {
        for (; ; )
        {
            try
            {
                final ReferenceWrapperWithDisposerRunnable item = (ReferenceWrapperWithDisposerRunnable) referenceQueue.remove();
                refs.remove(item);
                //
                // Delay in order to avoid freeing a reference that the GC has
                // decided is unreachable concurrently with its last use.
                //
                cleanupExecutor.schedule(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        item.dispose();
                    }
                }, cleanupDelay, TimeUnit.SECONDS);
            } catch (InterruptedException iex)
            {
                Thread.currentThread().interrupt();
            } catch (Throwable e)
            {
                if (LOG.isLoggable(Level.FINE))
                {
                    LOG.fine("exception in disposal thread: " + e.getMessage());
                }
            }
        }
    }

    private static class ReferenceWrapperWithDisposerRunnable
            extends PhantomReference
//        implements Comparable
    {


        private final Runnable disposer;
        private final String label;

        /**
         * Creates a new phantom reference that refers to the given object and
         * is registered with the given queue.
         *
         * 

It is possible to create a phantom reference with a null * queue, but such a reference is completely useless: Its get * method will always return null and, since it does not have a queue, it * will never be enqueued. * * @param referent the object the new phantom reference will refer to * @param q the queue with which the reference is to be registered, * or null if registration is not required */ public ReferenceWrapperWithDisposerRunnable(Disposable referent, ReferenceQueue q) { super(referent, q); this.disposer = referent.getDisposeAction(); this.label = referent.toString(); } public void dispose() { disposer.run(); } @Override public String toString() { return label; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy