Home / Class/ ObjectCleaner Class — netty Architecture

ObjectCleaner Class — netty Architecture

Architecture documentation for the ObjectCleaner class in ObjectCleaner.java from the netty codebase.

Entity Profile

Dependency Diagram

graph TD
  f13b11d8_c490_1490_6aa6_8adffebc235a["ObjectCleaner"]
  8a87836a_5ade_7441_afab_a2859936e04e["ObjectCleaner.java"]
  f13b11d8_c490_1490_6aa6_8adffebc235a -->|defined in| 8a87836a_5ade_7441_afab_a2859936e04e
  e0d2f0f6_13c1_e3bf_5723_afb50e0244db["register()"]
  f13b11d8_c490_1490_6aa6_8adffebc235a -->|method| e0d2f0f6_13c1_e3bf_5723_afb50e0244db
  6f7a75ef_06b2_5ff7_b7fd_659ec783c55b["getLiveSetCount()"]
  f13b11d8_c490_1490_6aa6_8adffebc235a -->|method| 6f7a75ef_06b2_5ff7_b7fd_659ec783c55b
  952f3024_28ac_4cdf_f6d7_72d6869e4011["ObjectCleaner()"]
  f13b11d8_c490_1490_6aa6_8adffebc235a -->|method| 952f3024_28ac_4cdf_f6d7_72d6869e4011

Relationship Graph

Source Code

common/src/main/java/io/netty/util/internal/ObjectCleaner.java lines 35–158

public final class ObjectCleaner {
    private static final int REFERENCE_QUEUE_POLL_TIMEOUT_MS =
            max(500, getInt("io.netty.util.internal.ObjectCleaner.refQueuePollTimeout", 10000));

    // Package-private for testing
    static final String CLEANER_THREAD_NAME = ObjectCleaner.class.getSimpleName() + "Thread";
    // This will hold a reference to the AutomaticCleanerReference which will be removed once we called cleanup()
    private static final Set<AutomaticCleanerReference> LIVE_SET = ConcurrentHashMap.newKeySet();
    private static final ReferenceQueue<Object> REFERENCE_QUEUE = new ReferenceQueue<>();
    private static final AtomicBoolean CLEANER_RUNNING = new AtomicBoolean(false);
    private static final Runnable CLEANER_TASK = new Runnable() {
        @Override
        public void run() {
            boolean interrupted = false;
            for (;;) {
                // Keep on processing as long as the LIVE_SET is not empty and once it becomes empty
                // See if we can let this thread complete.
                while (!LIVE_SET.isEmpty()) {
                    final AutomaticCleanerReference reference;
                    try {
                        reference = (AutomaticCleanerReference) REFERENCE_QUEUE.remove(REFERENCE_QUEUE_POLL_TIMEOUT_MS);
                    } catch (InterruptedException ex) {
                        // Just consume and move on
                        interrupted = true;
                        continue;
                    }
                    if (reference != null) {
                        try {
                            reference.cleanup();
                        } catch (Throwable ignored) {
                            // ignore exceptions, and don't log in case the logger throws an exception, blocks, or has
                            // other unexpected side effects.
                        }
                        LIVE_SET.remove(reference);
                    }
                }
                CLEANER_RUNNING.set(false);

                // Its important to first access the LIVE_SET and then CLEANER_RUNNING to ensure correct
                // behavior in multi-threaded environments.
                if (LIVE_SET.isEmpty() || !CLEANER_RUNNING.compareAndSet(false, true)) {
                    // There was nothing added after we set STARTED to false or some other cleanup Thread
                    // was started already so its safe to let this Thread complete now.
                    break;
                }
            }
            if (interrupted) {
                // As we caught the InterruptedException above we should mark the Thread as interrupted.
                Thread.currentThread().interrupt();
            }
        }
    };

    /**
     * Register the given {@link Object} for which the {@link Runnable} will be executed once there are no references
     * to the object anymore.
     *
     * This should only be used if there are no other ways to execute some cleanup once the Object is not reachable
     * anymore because it is not a cheap way to handle the cleanup.
     */
    public static void register(Object object, Runnable cleanupTask) {
        AutomaticCleanerReference reference = new AutomaticCleanerReference(object,
                ObjectUtil.checkNotNull(cleanupTask, "cleanupTask"));
        // Its important to add the reference to the LIVE_SET before we access CLEANER_RUNNING to ensure correct
        // behavior in multi-threaded environments.
        LIVE_SET.add(reference);

        // Check if there is already a cleaner running.
        if (CLEANER_RUNNING.compareAndSet(false, true)) {
            final Thread cleanupThread = new FastThreadLocalThread(CLEANER_TASK);
            cleanupThread.setPriority(Thread.MIN_PRIORITY);
            // Set to null to ensure we not create classloader leaks by holding a strong reference to the inherited
            // classloader.
            // See:
            // - https://github.com/netty/netty/issues/7290
            // - https://bugs.openjdk.java.net/browse/JDK-7008595
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                @Override
                public Void run() {
                    cleanupThread.setContextClassLoader(null);
                    return null;

Frequently Asked Questions

What is the ObjectCleaner class?
ObjectCleaner is a class in the netty codebase, defined in common/src/main/java/io/netty/util/internal/ObjectCleaner.java.
Where is ObjectCleaner defined?
ObjectCleaner is defined in common/src/main/java/io/netty/util/internal/ObjectCleaner.java at line 35.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free