{"record":{"id":"985d2d91521886a7","repo":"alibaba/arthas","slug":"can-not-find-arthas-spy-jar","errorCode":null,"errorMessage":"can not find ${ARTHAS_SPY_JAR}","messagePattern":"can not find (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"core/src/main/java/com/taobao/arthas/core/server/ArthasBootstrap.java","lineNumber":229,"sourceCode":"\n        // 将Spy添加到BootstrapClassLoader\n        ClassLoader parent = ClassLoader.getSystemClassLoader().getParent();\n        Class<?> spyClass = null;\n        if (parent != null) {\n            try {\n                spyClass =parent.loadClass(\"java.arthas.SpyAPI\");\n            } catch (Throwable e) {\n                // ignore\n            }\n        }\n        if (spyClass == null) {\n            CodeSource codeSource = ArthasBootstrap.class.getProtectionDomain().getCodeSource();\n            if (codeSource != null) {\n                File arthasCoreJarFile = new File(codeSource.getLocation().toURI().getSchemeSpecificPart());\n                File spyJarFile = new File(arthasCoreJarFile.getParentFile(), ARTHAS_SPY_JAR);\n                instrumentation.appendToBootstrapClassLoaderSearch(new JarFile(spyJarFile));\n            } else {\n                throw new IllegalStateException(\"can not find \" + ARTHAS_SPY_JAR);\n            }\n        }\n    }\n\n    void enhanceClassLoader() throws IOException, UnmodifiableClassException {\n        if (configure.getEnhanceLoaders() == null) {\n            return;\n        }\n        Set<String> loaders = new HashSet<String>();\n        for (String s : configure.getEnhanceLoaders().split(\",\")) {\n            loaders.add(s.trim());\n        }\n\n        // 增强 ClassLoader#loadClsss ，解决一些ClassLoader加载不到 SpyAPI的问题\n        // https://github.com/alibaba/arthas/issues/1596\n        byte[] classBytes = IOUtils.getBytes(ArthasBootstrap.class.getClassLoader()\n                .getResourceAsStream(ClassLoader_Instrument.class.getName().replace('.', '/') + \".class\"));\n","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/alibaba/arthas/blob/21cf2e9ba52b305290be7223b980ff504bb9cb5b/core/src/main/java/com/taobao/arthas/core/server/ArthasBootstrap.java#L211-L247","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: custom in-memory classloader with no protection domain\nClassLoader cl = new URLClassLoader(new URL[0]);\n// arthas core loaded here -> getProtectionDomain().getCodeSource() == null\n\n// after: load from a real jar URL so CodeSource resolves\nFile coreJar = new File(libDir, \"arthas-core.jar\");\nURLClassLoader cl = new URLClassLoader(new URL[]{ coreJar.toURI().toURL() });","handlingStrategy":"validation","validationCode":"// Before calling ArthasBootstrap, verify the spy jar is resolvable\nFile coreJar = new File(ArthasBootstrap.class\n    .getProtectionDomain().getCodeSource().getLocation().toURI());\nFile spyJar = new File(coreJar.getParentFile(), \"arthas-spy.jar\");\nif (!spyJar.exists()) {\n    throw new IllegalStateException(\"arthas-spy.jar missing at \" + spyJar);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["bootstrap","classpath","instrumentation","spy-jar"],"backgroundTag":null,"analyzedSha":"21cf2e9ba52b305290be7223b980ff504bb9cb5b","analyzedAt":"2026-08-14T00:57:07.243Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}