You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

错误原因

  1. 处理.java文件:Soot的Java前端要求从包结构的根目录读取源文件,而非直接读取包所在的子目录。当类声明package tests;时,Soot期望在tests目录的上级目录(项目根目录)找到tests/FooBar.java,而非直接把./tests作为根目录读取。
  2. 处理.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文件

  1. 编译时保留包结构:
    使用命令指定输出目录(如bin),生成符合包结构的.class文件:
    javac tests/*.java -d bin
    
    此时bin目录下会生成tests/FooBar.class和tests/Pack.class。
  2. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 02:15:42