alibaba/arthas · critical · IllegalStateException

can not find ${ARTHAS_SPY_JAR}

Error message

can not find ${ARTHAS_SPY_JAR}

What it means

Thrown during Arthas bootstrap initialization (initSpy) when the SpyAPI class cannot be loaded from the parent classloader AND the arthas-core jar's ProtectionDomain has a null CodeSource. Without a CodeSource the code cannot locate the sibling arthas-spy.jar to append to the bootstrap classloader search path, so instrumentation of the target JVM is impossible. This is a hard fatal error that prevents Arthas from attaching at all.

Source

Thrown at core/src/main/java/com/taobao/arthas/core/server/ArthasBootstrap.java:229

        // 将Spy添加到BootstrapClassLoader
        ClassLoader parent = ClassLoader.getSystemClassLoader().getParent();
        Class<?> spyClass = null;
        if (parent != null) {
            try {
                spyClass =parent.loadClass("java.arthas.SpyAPI");
            } catch (Throwable e) {
                // ignore
            }
        }
        if (spyClass == null) {
            CodeSource codeSource = ArthasBootstrap.class.getProtectionDomain().getCodeSource();
            if (codeSource != null) {
                File arthasCoreJarFile = new File(codeSource.getLocation().toURI().getSchemeSpecificPart());
                File spyJarFile = new File(arthasCoreJarFile.getParentFile(), ARTHAS_SPY_JAR);
                instrumentation.appendToBootstrapClassLoaderSearch(new JarFile(spyJarFile));
            } else {
                throw new IllegalStateException("can not find " + ARTHAS_SPY_JAR);
            }
        }
    }

    void enhanceClassLoader() throws IOException, UnmodifiableClassException {
        if (configure.getEnhanceLoaders() == null) {
            return;
        }
        Set<String> loaders = new HashSet<String>();
        for (String s : configure.getEnhanceLoaders().split(",")) {
            loaders.add(s.trim());
        }

        // 增强 ClassLoader#loadClsss ,解决一些ClassLoader加载不到 SpyAPI的问题
        // https://github.com/alibaba/arthas/issues/1596
        byte[] classBytes = IOUtils.getBytes(ArthasBootstrap.class.getClassLoader()
                .getResourceAsStream(ClassLoader_Instrument.class.getName().replace('.', '/') + ".class"));

View on GitHub (pinned to 21cf2e9ba5)

Solutions

  1. Ensure arthas-spy.jar sits in the same directory as arthas-core.jar (the code resolves it via getParentFile of the core jar location).
  2. Attach Arthas using the official as.sh / java -jar arthas-boot.jar workflow so the standard jar layout is preserved, rather than a custom embedding that loses the CodeSource.
  3. Pre-load SpyAPI into the parent/system classloader before Arthas initializes, bypassing the CodeSource lookup entirely.
  4. If embedding Arthas programmatically, set a ProtectionDomain with a real CodeSource on the classloader that loads arthas-core.

Example fix

// before: custom in-memory classloader with no protection domain
ClassLoader cl = new URLClassLoader(new URL[0]);
// arthas core loaded here -> getProtectionDomain().getCodeSource() == null

// after: load from a real jar URL so CodeSource resolves
File coreJar = new File(libDir, "arthas-core.jar");
URLClassLoader cl = new URLClassLoader(new URL[]{ coreJar.toURI().toURL() });
Defensive patterns

Strategy: validation

Validate before calling

// Before calling ArthasBootstrap, verify the spy jar is resolvable
File coreJar = new File(ArthasBootstrap.class
    .getProtectionDomain().getCodeSource().getLocation().toURI());
File spyJar = new File(coreJar.getParentFile(), "arthas-spy.jar");
if (!spyJar.exists()) {
    throw new IllegalStateException("arthas-spy.jar missing at " + spyJar);
}

Prevention

When it happens

Trigger: Arthas is loaded by a custom ClassLoader whose ProtectionDomain returns null from getCodeSource() (e.g. an in-memory classloader, a dynamically-generated proxy classloader, or a container that strips protection domains). The parent classloader also fails to find java.arthas.SpyAPI, so both fallback paths are exhausted.

Common situations: Running Arthas inside certain OSGi containers, custom plugin loaders, or agents that redefine classes without preserving the code source. Also seen when arthas-spy.jar is missing from the lib directory but the core jar was loaded from a non-standard location, or when a security manager strips ProtectionDomain info.

Related errors


AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14). Data as JSON: /api/errors/985d2d91521886a7. Report an issue: GitHub.