apache/druid · warning · java.lang.RuntimeException

Unable to create cleaner

Error message

Unable to create cleaner

What it means

Within Cleaners.lookupCleaner, after reflectively finding the cleaner factory MethodHandle, invoking it to instantiate the cleaner object failed. This RuntimeException wraps that Throwable and indicates the JDK's cleaner internals exist but cannot be instantiated via reflection in this runtime.

Solutions

  1. Switch to a mainstream OpenJDK build whose internal Cleaner API matches Druid's expectations.
  2. Upgrade Druid to a version whose Cleaners implementation supports your JDK.
  3. Handle this RuntimeException upstream and fall back to GC-based resource cleanup.

Example fix

// before
Cleanable c = Cleaners.register(obj, action); // may throw RuntimeException
// after
try {
  Cleanable c = Cleaners.register(obj, action);
} catch (RuntimeException | UnsupportedOperationException e) {
  // fallback: rely on finalizer/GC
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  Cleaners.register(obj, action);
} catch (RuntimeException e) {
  LOG.warn(e, "cleaner init/registration failed");
}

Prevention

When it happens

Trigger: lookupCleaner resolving the cleaner creation MethodHandle (e.g. Cleaner.create or CleanerFactory.cleaner) but create.invoke() throwing at runtime due to incompatible internal API signatures, access restrictions, or initialization failure on the JVM.

Common situations: Unusual JDK builds whose internal Cleaner API differs from what the reflective lookup expects; security managers or instrumentation agents rewriting internals; partial JDK upgrades where the class exists but construction fails.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/dfb89d25b9036d01. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/java/util/common/Cleaners.java:83

    catch (ReflectiveOperationException | RuntimeException e) {
      throw new UnsupportedOperationException("Cleaning is not support on this platform, because internal " +
                                              "Java APIs are not compatible with this Druid version", e);
    }
  }

  private static Cleaner lookupCleaner(MethodHandles.Lookup lookup) throws ReflectiveOperationException
  {
    Class<?> cleaner = Class.forName("java.lang.ref.Cleaner");
    Class<?> cleanable = Class.forName("java.lang.ref.Cleaner$Cleanable");

    MethodHandle create = lookup.findStatic(cleaner, "create", MethodType.methodType(cleaner));

    Object theCleaner;
    try {
      theCleaner = create.invoke();
    }
    catch (Throwable t) {
      throw new RuntimeException("Unable to create cleaner", t);
    }

    MethodHandle register = lookup.findVirtual(
        cleaner,
        "register",
        MethodType.methodType(cleanable, Object.class, Runnable.class)
    ).bindTo(theCleaner);

    MethodHandle clean = lookup.findVirtual(cleanable, "clean", MethodType.methodType(void.class));

    return new CleanerImpl(register, clean);
  }

  public static Cleanable register(Object object, Runnable runnable)
  {
    if (CLEANER == null) {
      throw new UnsupportedOperationException(CLEANER_NOT_SUPPORTED_EXCEPTION);
    }

View on GitHub (pinned to 9b90983fd2)