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

为何SOOT无法检测到动态加载类中的方法调用?

SOOT调用图无法识别实例方法调用的解决方案

问题场景

作为SOOT初学者,创建Calculator类实例后,其add方法的调用关系始终无法在生成的调用图中找到,即使打印所有调用边也看不到该方法的调用记录。

待分析源码

package com.example.hello;

public class TestInputMain {
    public static void main(String[] args) {

        Calculator calc = new Calculator();  // 同包下自定义的类

        int result = calc.add(10, 20); // 无法在调用图中找到该调用!

        System.out.println("The result of adding 10 and 20 is " + result);
    }
}

使用的SOOT配置代码

// 设置调用图
String[] sootArgs = {
    "-pp",
    "-process-dir", jarFilePath, // 已打包为jar,不打包结果一致
    "-allow-phantom-refs",
    "-no-bodies-for-excluded", 
    "-whole-program",
    "-verbose",
    "-p", "cg.cha", "enabled:true",
    "-dynamic-dir", jarFilePath,
};
Options.v().parse(sootArgs);

String sootClassPath = jarFilePath;
Options.v().set_soot_classpath(sootClassPath);

Scene.v().loadNecessaryClasses();

PackManager.v().getPack("wjtp").add(new Transform("wjtp.myTransform", new SceneTransformer() {
    @Override
    protected void internalTransform(String phaseName, Map<String, String> options) {
        CallGraph cg = Scene.v().getCallGraph();
        // 打印调用图中所有边
        CallGraph callgraph = Scene.v().getCallGraph();
        Iterator<Edge> edgesdebug = callgraph.iterator();
        while (edgesdebug.hasNext()) {
            Edge it = edgesdebug.next();
            System.out.println("??????" + it.src() + " =>> " + it.tgt());
        }
    }
}));

排查与解决步骤

  • 确保目标类被SOOT完整加载:
    确认Calculator的class文件在jarFilePath指向的资源中,且手动强制加载该类(避免SOOT自动加载时遗漏),在Scene.v().loadNecessaryClasses()后添加:

    Scene.v().loadClass("com.example.hello.Calculator", SootClass.BODIES);
    

    该操作会强制SOOT加载类的方法体,为调用图分析提供必要的代码信息。

  • 更换调用图分析算法:
    CHA(类层次分析)属于保守型算法,对直接实例化的类调用可能识别不足。可以替换为更精确的RTA或Spark算法:

    • 启用RTA:将sootArgs中的"-p", "cg.cha", "enabled:true"替换为"-p", "cg.rta", "enabled:true"
    • 启用Spark:替换为"-p", "cg.spark", "enabled:true"
  • 确认阶段执行顺序:
    调用图构建属于cg阶段,若自定义Transform的执行时机过早,可能访问到未完成构建的调用图。可以在访问调用图前强制触发调用图构建:

    PackManager.v().getPack("cg").apply();
    
  • 完善全程序模式配置:
    启用-whole-program时,添加-include-all参数强制SOOT处理类路径下所有相关类,避免遗漏目标类:

    String[] sootArgs = {
        // 原有参数
        "-include-all",
    };
    

验证方式

修改配置后重新运行SOOT,检查打印的调用边是否包含TestInputMain.main到Calculator.add的调用关系。若仍未找到,可通过-verbose日志确认Calculator类是否被SOOT正确加载。

内容的提问来源于stack exchange,提问作者Chenyang Zhu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 21:17:33