Soot分析包内Java文件报错:无法找到类的技术问询
问题描述
tests目录下有两个声明了package tests;的Java文件(Pack.java、FooBar.java),使用Soot的Main.java配置分析构建调用图时,无论直接分析.java还是编译后的.class文件,都会报找不到类的错误(提示包配置问题),移除包声明后可正常运行,求解决办法。
相关代码
Main.java配置代码
import java.util.Collections; import soot.Options; import soot.Scene; public class Main { static void setupSoot() { Options.v().set_prepend_classpath(true); Options.v().set_process_dir(Collections.singletonList("./tests")); Options.v().set_whole_program(true); Scene.v().loadNecessaryClasses(); } // 以下写法同样报错 //static void setupSoot() { // Options.v().set_prepend_classpath(true); // Options.v().set_process_dir(Collections.singletonList("./tests")); // Scene.v().loadClassAndSupport("FooBar"); //} public static void main(String[] args) { setupSoot(); // .... } }
测试文件代码
Pack.java
package tests; public class Pack { public static void main(String[] args) { int s = 10; } }
FooBar.java
package tests; public class FooBar { public static void main(String[] args) { FooBar callFooBar = new FooBar(); callFooBar.foo(10); } void foo(int a) { bar(a); } void bar(int a) { for (int i = 0; i < a; i++) { i += a; } } }
报错信息
直接分析.java文件时的报错
Exception in thread "main" java.lang.RuntimeException: Error: couldn't find class: FooBar are the packages set properly? at soot.JastAddInitialResolver.resolveFromJavaFile(JastAddInitialResolver.java:119) at soot.JavaClassSource.resolve(JavaClassSource.java:69) at soot.SootResolver.bringToHierarchyUnchecked(SootResolver.java:253) at soot.SootResolver.bringToHierarchy(SootResolver.java:221) at soot.SootResolver.bringToSignatures(SootResolver.java:292) at soot.SootResolver.bringToBodies(SootResolver.java:332) at soot.SootResolver.processResolveWorklist(SootResolver.java:171) at soot.SootResolver.resolveClass(SootResolver.java:141) at soot.Scene.loadClass(Scene.java:1009) at soot.Scene.loadClassAndSupport(Scene.java:994) at soot.Scene.loadNecessaryClasses(Scene.java:1822) at Main.setupSoot(Main.java:18) at Main.main(Main.java:21)
分析编译后的.class文件时的报错
Exception in thread "main" soot.SootResolver$SootClassNotFoundException: couldn't find class: tests.FooBar (is your soot-class-path set properly?) at soot.SootResolver.bringToHierarchyUnchecked(SootResolver.java:245) at soot.SootResolver.bringToHierarchy(SootResolver.java:221) at soot.SootResolver.bringToSignatures(SootResolver.java:292) at soot.SootResolver.bringToBodies(SootResolver.java:332) at soot.SootResolver.processResolveWorklist(SootResolver.java:171) at soot.SootResolver.resolveClass(SootResolver.java:141) at soot.Scene.loadClass(Scene.java:1009) at soot.Scene.loadClassAndSupport(Scene.java:994) at soot.Scene.loadNecessaryClasses(Scene.java:1822) at Main.setupSoot(Main.java:18) at Main.main(Main.java:21)
错误原因
- 处理.java文件:Soot的Java前端要求从包结构的根目录读取源文件,而非直接读取包所在的子目录。当类声明
package tests;时,Soot期望在tests目录的上级目录(项目根目录)找到tests/FooBar.java,而非直接把./tests作为根目录读取。 - 处理.class文件:编译后的.class文件必须保留包结构(即
tests/FooBar.class),且需要将包结构的根目录加入Soot类路径;同时加载类时必须使用全限定类名(tests.FooBar),不能只写类名。
解决方法
情况1:直接处理.java源文件
修改Soot的process_dir为包结构的根目录(项目根目录),可显式指定要处理的类:
static void setupSoot() { Options.v().set_prepend_classpath(true); // 设置为tests目录的上级目录(项目根目录) Options.v().set_process_dir(Collections.singletonList(".")); // 可选:显式指定要处理的全限定类名 Options.v().set_classes(Collections.singletonList("tests.FooBar")); Options.v().set_whole_program(true); Scene.v().loadNecessaryClasses(); }
情况2:处理编译后的.class文件
- 编译时保留包结构:
使用命令指定输出目录(如bin),生成符合包结构的.class文件:
此时javac tests/*.java -d binbin目录下会生成tests/FooBar.class和tests/Pack.class。 - 修改Soot配置,指向包结构根目录并使用全限定类名加载:
static void setupSoot() { Options.v().set_prepend_classpath(true); // 设置process_dir为.class文件的包根目录 Options.v().set_process_dir(Collections.singletonList("./bin")); Options.v().set_whole_program(true); // 加载类时使用全限定类名 Scene.v().loadClassAndSupport("tests.FooBar"); Scene.v().loadNecessaryClasses(); }
验证要点
- 源文件/.class文件的目录结构必须与包声明完全匹配:
package tests;对应文件放在tests/目录下,且该目录的上级是类路径根目录。 - 加载类时必须使用全限定类名(包名+类名),不能仅写类名。
- Soot的
process_dir需要指向包结构的根目录,而非包所在的子目录。
内容的提问来源于stack exchange,提问作者MissSirius
相关产品推荐
相关产品推荐

