apache/pulsar · error · RuntimeException

Class must have a no-arg constructor

Error message

Class  must have a no-arg constructor

What it means

createInstance() calls setAccessible(true) on the no-arg constructor and then newInstance(). IllegalAccessException means the constructor is not accessible from the caller (e.g. package-private/private class or constructor, or sealed module), and Pulsar rethrows as RuntimeException("Class X must have a no-arg constructor").

Source

Thrown at pulsar-functions/runtime-all/src/main/java/org/apache/pulsar/functions/instance/JavaInstanceMain.java:150

                                        ClassLoader classLoader) {
        Class<?> theCls;
        try {
            theCls = Class.forName(userClassName, true, classLoader);
        } catch (ClassNotFoundException | NoClassDefFoundError cnfe) {
            throw new RuntimeException("Class " + userClassName + " must be in class path", cnfe);
        }
        Object result;
        try {
            Constructor<?> meth = theCls.getDeclaredConstructor();
            meth.setAccessible(true);

            result = meth.newInstance();
        } catch (InstantiationException ie) {
            throw new RuntimeException("User class must be concrete", ie);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException("Class " + userClassName + " doesn't have such method", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Class " + userClassName + " must have a no-arg constructor", e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("Class " + userClassName + " constructor throws exception", e);
        }
        return result;
    }

    public static ClassLoader loadJar(ClassLoader parent, File[] jars) throws MalformedURLException {
        URL[] urls = new URL[jars.length];
        for (int i = 0; i < jars.length; i++) {
            urls[i] = jars[i].toURI().toURL();
        }
        return new URLClassLoader(urls, parent);
    }

    public static boolean isBlank(String str) {
        int strLen;
        if (str != null && (strLen = str.length()) != 0) {
            for (int i = 0; i < strLen; ++i) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Declare the function class public and give it a public no-arg constructor.
  2. Move inner/nested function classes to top-level public classes.
  3. If running on a modular JDK, open the function package (--add-opens) or avoid modules for the function jar.
  4. Ensure no SecurityManager policy denies ReflectPermission/accessDeclaredMembers.

Example fix

// before
class MyFunction implements Function<String, Integer> { ... }
// after
public class MyFunction implements Function<String, Integer> { public MyFunction() {} ... }
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName(className);
if (!java.lang.reflect.Modifier.isPublic(c.getModifiers())) throw new IllegalArgumentException("Function class must be public");
java.lang.reflect.Constructor<?> k = c.getDeclaredConstructor();
k.setAccessible(true); // will throw here in your CI before deployment if inaccessible

Type guard

boolean publiclyInstantiable(String fcn) { try { Class<?> c = Class.forName(fcn); return java.lang.reflect.Modifier.isPublic(c.getModifiers()) && java.lang.reflect.Modifier.isPublic(c.getDeclaredConstructor().getModifiers()); } catch (Throwable t) { return false; } }

Try / catch

try { Object f = JavaInstanceMain.createInstance(className, cl); } catch (RuntimeException e) { if (e.getMessage().contains("no-arg constructor")) { System.err.println("Make " + className + " and its constructor public"); } throw e; }

Prevention

When it happens

Trigger: Function class or its no-arg constructor declared private/package-private; class itself is package-private (not public); Java module/SecurityManager blocking setAccessible.

Common situations: Defining the function as a nested or package-private class; making the constructor private to enforce single instantiation; JPMS strong encapsulation in newer JDKs.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/6c4aa9b6818cdff5. Report an issue: GitHub.