SonarSource/sonarqube · error · IllegalArgumentException

Can not find the MBean interface of class

Error message

Can not find the MBean interface of class 

What it means

guessMBeanInterface scans the instance's implemented interfaces for one whose name ends with 'MBean'. If none is found it throws IllegalArgumentException, because StandardMBean requires such an interface.

Solutions

  1. Make the class implement a public interface whose name ends with 'MBean'
  2. Restore the MBean suffix if a rename removed it
  3. Ensure the interface is public (StandardMBean requirement)
  4. Pass the correct managed object to Jmx.register

Example fix

// before
public interface Watchdog { void check(); }
class WatchdogImpl implements Watchdog {}
// after
public interface WatchdogMBean { void check(); }
class WatchdogImpl implements WatchdogMBean {}
Defensive patterns

Strategy: type-guard

Validate before calling

boolean hasMBeanInterface(Object o) {
  return Arrays.stream(o.getClass().getInterfaces())
    .anyMatch(i -> i.getName().endsWith("MBean"));
}

Type guard

static boolean isRegisterable(Object instance) {
  return Arrays.stream(instance.getClass().getInterfaces())
    .anyMatch(i -> java.lang.reflect.Modifier.isPublic(i.getModifiers()) && i.getName().endsWith("MBean"));
}

Try / catch

try { Jmx.register(name, instance); } catch (IllegalArgumentException e) { throw new IllegalStateException("Object " + instance + " lacks an MBean interface", e); }

Prevention

When it happens

Trigger: register(name, instance) where instance's class implements no interface named *MBean (or the matching interface is not public).

Common situations: Refactoring renamed the interface dropping the MBean suffix; object implements only non-public interfaces; wrong object passed to register.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/12fe8c60ea0c4647. Report an issue: GitHub.

Appendix: source

Thrown at server/sonar-process/src/main/java/org/sonar/process/Jmx.java:72

   * MBeans have multiple conventions, including:
   * 1. name of interface is suffixed by "MBean"
   * 2. name of implementation is the name of the interface without "MBean"
   * 3. implementation and interface must be in the same package
   * To avoid the last convention, we wrap the mbean within a StandardMBean. That
   * requires to find the related interface.
   */

  private static Class<Object> guessMBeanInterface(Object instance) {
    Class<Object> mbeanInterface = null;
    Class<Object>[] interfaces = (Class<Object>[])instance.getClass().getInterfaces();
    for (Class<Object> anInterface : interfaces) {
      if (anInterface.getName().endsWith("MBean")) {
        mbeanInterface = anInterface;
        break;
      }
    }
    if (mbeanInterface == null) {
      throw new IllegalArgumentException("Can not find the MBean interface of class " + instance.getClass().getName());
    }
    return mbeanInterface;
  }

  /**
   * Unregister a MBean from JMX server. Errors are ignored and logged as warnings.
   */
  public static void unregister(String name) {
    try {
      ManagementFactory.getPlatformMBeanServer().unregisterMBean(new ObjectName(name));
    } catch (Exception e) {
      LoggerFactory.getLogger(Jmx.class).warn("Can not unregister MBean [{}]", name, e);
    }
  }
}

View on GitHub (pinned to 184c821202)