What is the use of the Cleaner class in Java 9?



In this article, we will learn about the use of the Cleaner class in Java 9. Below, we will first tell the basic usage and then we will know how we can use the Cleaner method practically.

Garbage Collector

An Object that has been created during the program execution is automatically removed by the Garbage Collector (GC). When an object not referenced by any thread and when JVM determines that this object can't be accessed, then it can be eligible for garbage collection.

The finalize() method

The Object class has a finalize() method, which is automatically called by GC before it attempts to remove the object from the heap. The finalize() method has many disadvantages:

  • Unreliable
  • Slow

Cleaner class

In Java 9, the finalize() method has been deprecated and a new class java.lang.ref.Cleaner added to garbage collection management. An object of Cleaner class gets notified automatically when an object becomes eligible for garbage collection. An object that is being garbage collected needs to be registered with the cleaner object by using the register() method.

The Cleaner variable should be shared across different classes. The Cleaner variable is declared as a static variable and should never be an instance variable.

Basic cleaner usage

Below is an example to use the Cleaner class in Java:

import java.lang.ref.Cleaner;
public class CleanerTest {
   public static void main(String args[]) {
      System.out.println("TutorialsPoint");
      Cleaner cleaner = Cleaner.create();
      if(true) {
         CleanerTest myObject = new CleanerTest();
            cleaner.register(myObject, new State());    // register cleaner
      }
      for(int i = 1; i <= 10000; i++) {
         String[] largeObject = new String[1000];
         try {
            Thread.sleep(1);
         } catch(InterruptedException e) {
              e.printStackTrace();
         }
      }
   }
   private static class State implements Runnable {
      public void run() {
         System.out.print("Cleaning action");
      }
   }
}

Output

TutorialsPoint 
Cleaning action

In the above program, we are using the inner class. The inner class instance would hold a reference to the outer class instance regardless of whether they access their instance variable or not. We cannot use the above program practically as it relies totally on the Garbage Collector and doesn't have any control over when the cleanup is triggered.

Effective Use of Cleaner 

In the below example, we can see the effective use of a cleaner with AutoCloseable and Try-With-Resources. We will not call the cleaning action explicitly, and the Cleaner stays intact as our safety net.

  • Implement the AutoCloseable interface.
  • Place the cleaning action call in the close() method.
  • ResourceHolder can now be used in a try-with-resources block.

This can be achieved by having the ResourceHolder class:

import java.lang.ref.Cleaner.Cleanable;

public class ResourceHolder implements AutoCloseable {

    private final ExternalResource externalResource;

    private final Cleaner.Cleanable cleanable;

    public ResourceHolder(ExternalResource externalResource) {
        this.externalResource = externalResource;
        cleanable = AppUtil.getCleaner().register(this, new CleaningAction(externalResource));
    }

    public void doSomethingWithResource() {
        System.out.printf("Do something extra with the important resource: %s \n", this.externalResource);
    }
    @Override
    public void close() {
        System.out.println("cleaning action invoked by the close method");
        cleanable.clean();
    }

    static class CleaningAction implements Runnable {
        private ExternalResource externalResource;

        CleaningAction(ExternalResource externalResource) {
            this.externalResource = externalResource;
        }

        @Override
        public void run() {
//            cleaning up the important resources
            System.out.println("cleaning logic inprogress, releasing up very important resources");
            externalResource = null;
        }
    }

    public static void main(String[] args) {
//      This is an effective way to use cleaners with instances that hold crucial resources
        try (ResourceHolder resourceHolder = new ResourceHolder(new ExternalResource(1))) {
            resourceHolder.doSomethingWithResource();
            System.out.println("See you");
        }
/*
    In case the client code does not use the try-with-resource as expected,
    the Cleaner will act as the safety-net
*/
        ResourceHolder resourceHolder = new ResourceHolder(new ExternalResource(2));
        resourceHolder.doSomethingWithResource();
        resourceHolder = null;
        System.gc(); // to facilitate the running of the cleaning action
    }
}
Alshifa Hasnain
Alshifa Hasnain

Converting Code to Clarity

Updated on: 2025-06-10T18:41:30+05:30

977 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements