java - Lambda 表达式的烟灰调用图
问题描述
我想使用 Soot 创建一个调用图,它可以将 lambda 主体识别为可访问。
更准确地说,我想让 Soot 为下面的示例绘制调用图。
public class TestLambda3 {
public static void main(String[] args) {
method1();
}
public static void method1() {
List<TestLambda3> list = Arrays.asList(new TestLambda3(), new TestLambda3());
list.stream().forEach(x -> x.foo());
}
public void foo() {
bar();
}
public void bar() {
System.out.println("hi1");
}
}
在这里,我期望调用图将包含一条从main
一路到foo
then的路径bar
,lambda
在中间调用。我不确定为什么这条路不存在。我可以想象它是因为accept
在 ```java.util 中调用了方法的调用。",但我不想分析整个 java.util. ,Soot 有什么简单的方法可以在不分析 JDK 的情况下处理这个问题?
我的烟灰配置是
G.reset();
Options options = Options.v();
options.set_whole_program(true);
options.set_verbose(true);
options.setPhaseOption("jb", "use-original-names:true");
options.set_keep_line_number(true);
options.setPhaseOption("cg.cha", "enabled:true");
options.set_allow_phantom_refs(true);
options.set_no_bodies_for_excluded(true);
options.set_soot_classpath(String.join(":", Arrays.asList(Objects.requireNonNull(config.getTargetJar()))));
options.set_process_dir(Arrays.asList(config.getTargetJar()));
options.set_prepend_classpath(true);
Scene.v().loadNecessaryClasses();
SootClass c = Scene.v().forceResolve("TestLambda3",SootClass.BODIES);
c.setApplicationClass();
SootMethod method = c.getMethod("void main(java.lang.String[])");
List entryPoints = new ArrayList();
entryPoints.add(method);
Scene.v().setEntryPoints(entryPoints);
PackManager.v().getPack("wjpp").apply();
PackManager.v().getPack("cg").apply();
生成的调用图是:
STATIC edge: staticinvoke <TestLambda3: void method1()>() in <TestLambda3: void main(java.lang.String[])> ==> <TestLambda3: void method1()>
CLINIT edge: list = staticinvoke <java.util.Arrays: java.util.List asList(java.lang.Object[])>($stack1) in <TestLambda3: void method1()> ==> <java.util.Arrays: void <clinit>()>
STATIC edge: $stack8 = staticinvoke <TestLambda3$lambda_method1_0__1: java.util.function.Consumer bootstrap$()>() in <TestLambda3: void method1()> ==> <TestLambda3$lambda_method1_0__1: java.util.function.Consumer bootstrap$()>
STATIC edge: list = staticinvoke <java.util.Arrays: java.util.List asList(java.lang.Object[])>($stack1) in <TestLambda3: void method1()> ==> <java.util.Arrays: java.util.List asList(java.lang.Object[])>
CLINIT edge: list = staticinvoke <java.util.Arrays: java.util.List asList(java.lang.Object[])>($stack1) in <TestLambda3: void method1()> ==> <java.lang.Object: void <clinit>()>
CLINIT edge: staticinvoke <java.lang.Object: void registerNatives()>() in <java.lang.Object: void <clinit>()> ==> <java.lang.Object: void <clinit>()>
STATIC edge: staticinvoke <java.lang.Object: void registerNatives()>() in <java.lang.Object: void <clinit>()> ==> <java.lang.Object: void registerNatives()>
SPECIAL edge: specialinvoke $stack2.<TestLambda3: void <init>()>() in <TestLambda3: void method1()> ==> <TestLambda3: void <init>()>
SPECIAL edge: specialinvoke $stack4.<TestLambda3: void <init>()>() in <TestLambda3: void method1()> ==> <TestLambda3: void <init>()>
SPECIAL edge: specialinvoke $r0.<TestLambda3$lambda_method1_0__1: void <init>()>() in <TestLambda3$lambda_method1_0__1: java.util.function.Consumer bootstrap$()> ==> <TestLambda3$lambda_method1_0__1: void <init>()>
SPECIAL edge: specialinvoke this.<java.lang.Object: void <init>()>() in <TestLambda3: void <init>()> ==> <java.lang.Object: void <init>()>
FINALIZE edge: null in <java.lang.Object: void <init>()> ==> <java.lang.Object: void finalize()>
SPECIAL edge: specialinvoke $r0.<java.lang.Object: void <init>()>() in <TestLambda3$lambda_method1_0__1: void <init>()> ==> <java.lang.Object: void <init>()>
关于如何解决这个问题的任何建议?谢谢。
解决方案
推荐阅读
- html - 如何使页脚响应并使其上的文本水平对齐?
- html - 为什么 z-index 不与这两个正方形重叠?
- c++ - Qt 未定义的参考 vtable
- c# - 在 Revit 中过滤元素并设置参数
- javascript - 单击快速查看按钮时,Vue阻止路由器链接提交
- c# - 捕获 forloop 输出的最小和最快的方法
- html - 如何为div设置边距功能
- c++ - 在这种情况下,我的时间复杂性偏执是否合理?
- javascript - 升级到 expo SDK 37.0.0 后,我的 stackNavigator 标头高度增加了一倍
- android - 删除 Firebase AuthStateListener 以在 onPause() 上进行身份验证并将其添加回 onResume() 的目的