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
- Ensure arthas-spy.jar sits in the same directory as arthas-core.jar (the code resolves it via getParentFile of the core jar location).
- 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.
- Pre-load SpyAPI into the parent/system classloader before Arthas initializes, bypassing the CodeSource lookup entirely.
- 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
- Always use the official as.sh / arthas-boot.jar launcher which preserves the standard jar layout.
- Keep arthas-spy.jar in the same directory as arthas-core.jar.
- Avoid custom classloaders that strip ProtectionDomain when embedding Arthas.
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.