您应该考虑使用Soot 等程序分析工具。 Soot 有一些优秀的 API 可以分析最适合您目的的代码。例如,要检查两个类是否“语义相同”,您可以考虑(1)两个类是否具有相同(或相似的字段)(2)两个类是否具有相同(或相似的方法)。
字段在 Soot 中表示为 SootField。您将在要用于比较的 SootField 对象中拥有所有必要的信息。要检查两种方法的语义相似性,您可以检查它们的控制流图 (CFGs) 是否相似(详细信息在 this guide 的第 5.7 节中)。
关于如何使用烟灰的提示。
如果您的源目录是srcDir,Java Home 是javaHome,类列表是classNames,那么您可以使用以下代码 sn-p 以编程方式在 Soot 工具集中加载您的类。
String sootClassPath = srcDir + ":"
+ javaHome + "/jre/lib/rt.jar:"
+javaHome + "/jre/lib/jce.jar";
Options.v().set_output_format(Options.output_format_jimple);
Options.v().set_src_prec(Options.src_prec_java);
for (String className : classNames) { // // "className" is like a.b.Myclass
Options.v().classes().add(className);
}
Options.v().set_keep_line_number(true);
Options.v().set_allow_phantom_refs(true);
Scene.v().setSootClassPath(sootClassPath);
Scene.v().loadBasicClasses();
当你的类被加载后,你可以像下面这样访问一个类:
SootClass sClass = Scene.v().loadClassAndSupport(className); // "className" is like a.b.Myclass
现在您可以访问sClass 的字段和方法,如下所示:
Chain<SootField> fieldList = sClass.getFields(); // import soot.util.Chain;
List<SootMethod> methods = sClass.getMethods();
您可以迭代方法的CFG,如下所示以获取它的指令列表,
if (method.isConcrete()) {
List<Unit> instructionList = new ArrayList<>();
Body b = method.retrieveActiveBody();
DirectedGraph g = new ExceptionalUnitGraph(b);
Iterator gitr = g.iterator();
while (gitr.hasNext()) {
Unit unit = (Unit) gitr.next();
instructionList.add(unit);
}
}