pinpoint-apm/pinpoint · critical · IllegalStateException

Cannot access URLClassLoader.addURL(URL)

Error message

Cannot access URLClassLoader.addURL(URL)

What it means

URLClassLoaderHandler appends the plugin jar to URLClassLoader-based application classloaders by reflectively invoking the protected URLClassLoader.addURL(URL) method, resolved once in a static initializer with setAccessible(true). If the JVM cannot expose addURL (module encapsulation, SecurityManager, or JVM without the method), the static initializer throws IllegalStateException, failing agent startup. This handler is only used when the target classloader is a URLClassLoader.

Source

Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/classloading/URLClassLoaderHandler.java:46

import java.util.Objects;

/**
 * @author Woonduk Kang(emeroad)
 * @author jaehong.kim
 */
public class URLClassLoaderHandler implements ClassInjector {

    private final Logger logger = LogManager.getLogger(this.getClass());
    private final boolean isDebug = logger.isDebugEnabled();

    private static final Method ADD_URL;

    static {
        try {
            ADD_URL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
            ADD_URL.setAccessible(true);
        } catch (ReflectiveOperationException e) {
            throw new IllegalStateException("Cannot access URLClassLoader.addURL(URL)", e);
        }
    }

    private final PluginConfig pluginConfig;

    public URLClassLoaderHandler(PluginConfig pluginConfig) {
        this.pluginConfig = Objects.requireNonNull(pluginConfig, "pluginConfig");
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> Class<? extends T> injectClass(ClassLoader classLoader, String className) {
        try {
            if (classLoader instanceof URLClassLoader) {
                final URLClassLoader urlClassLoader = (URLClassLoader) classLoader;
                addPluginURLIfAbsent(urlClassLoader);
                return (Class<T>) urlClassLoader.loadClass(className);
            }

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Add --add-opens java.base/java.net=ALL-UNNAMED (and java.lang if the plain handler also fails) to the application's JVM launch flags.
  2. Grant ReflectPermission("suppressAccessChecks") to the pinpoint agent in the SecurityManager policy, or remove the SecurityManager if not required.
  3. Upgrade the pinpoint agent to a version supporting your JDK's encapsulation rules, or use a supported JDK combination.
  4. Confirm the application actually launches with a URLClassLoader and a supported launcher for the agent version.
  5. Check startup logs for the full IllegalStateException cause to distinguish 'method missing' from 'access denied'.

Example fix

// before
java -cp app.jar:legacy.jar com.app.Main
// after
java --add-opens java.base/java.net=ALL-UNNAMED -javaagent:$AGENT_HOME/pinpoint-bootstrap.jar -cp app.jar com.app.Main
Defensive patterns

Strategy: validation

Validate before calling

// preflight: confirm addURL is reflectively accessible before starting the agent
boolean canAddUrl = false;
try {
    Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
    m.setAccessible(true);
    canAddUrl = true;
} catch (ReflectiveOperationException e) {
    System.err.println("Agent unsupported: need --add-opens java.base/java.net=ALL-UNNAMED");
}
if (!canAddUrl) throw new IllegalStateException("JVM blocks URLClassLoader.addURL reflection; add --add-opens flags");

Type guard

static boolean supportsReflectiveAddURL() {
    try {
        Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
        m.setAccessible(true);
        return true;
    } catch (ReflectiveOperationException | SecurityException e) {
        return false;
    }
}

Try / catch

try {
    agentBootstrap.start();
} catch (IllegalStateException e) {
    if (e.getMessage().contains("Cannot access URLClassLoader.addURL")) {
        System.err.println("Restart JVM with: --add-opens java.base/java.net=ALL-UNNAMED");
    } else throw e;
}

Prevention

When it happens

Trigger: Agent startup instantiates URLClassLoaderHandler (from PluginClassInjector.from) and the static block runs: URLClassLoader.class.getDeclaredMethod("addURL", URL.class) fails or setAccessible(true) is rejected on JDK 9+ without --add-opens java.base/java.net=ALL-UNNAMED, or a SecurityManager denies ReflectPermission("suppressAccessChecks").

Common situations: Running the agent on JDK 16+ where default strong encapsulation blocks setAccessible on JDK internals; legacy SecurityManager policies applied to containerized apps; a custom/alternative JDK that hides protected addURL.

Related errors


AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/82e3a25b86966965. Report an issue: GitHub.