所以我有一个方法
public modifiers Foo foo(Bar bar){
blah;
blah;
veryInterestingStmt;
moreBlah();
return XYZ;
}
我现在要将此方法拆分为s.t.其中的所有内容都被提取到一个单独的方法中(以编程方式)。
即
public modifiers Foo foo(Bar bar){
return trulyFoo(bar);
}
public modifiers Foo trulyFoo(Bar bar){
blah;
blah;
veryInterestingStmt;
moreBlah();
return XYZ;
}
但我怎么做呢?
天真的
private void fracture(SootMethod sm) {
SootClass sc = sm.getDeclaringClass();
String auxMethodName = sm.getName() + FRACTURE_SUFFIX;
Type auxReturnType = sm.getReturnType();
List<Type>auxParamTypes = new LinkedList<>(sm.getParameterTypes());
int auxModifiers = sm.getModifiers();
SootMethod auxMethod = sc.addMethod(new SootMethod(auxMethodName,auxParamTypes,auxReturnType,auxModifiers));
Body body = sm.getActiveBody();
Body auxBody = Jimple.v().newBody(auxMethod);
auxMethod.setActiveBody(auxBody);
for(Local l : body.getLocals()){
auxBody.getLocals().add(l);
}
PatchingChain<Unit> units = body.getUnits();
PatchingChain<Unit> auxUnits = auxBody.getUnits();
Iterator<Unit> it = body.getUnits().snapshotIterator();
boolean passedFirstNonidentity = false;
while(it.hasNext()){
Stmt stmt = (Stmt) it.next();
if(!passedFirstNonidentity && !(stmt instanceof IdentityStmt)) {
passedFirstNonidentity = true;
//TODO: if added more parameters than original method had, add their identity stmts here
}
auxUnits.add(stmt);
// if(passedFirstNonidentity) units.remove(stmt); //TODO: uncomment this and later add call to {@code auxMethod}
}
}
}
不起作用。如果我跑,请说
DirectedGraph dg = new ExceptionalUnitGraph(auxMethod.getActiveBody());
我得到了
java.lang.RuntimeException: Unit graph contains jump to non-existing target
at soot.toolkits.graph.UnitGraph.buildUnexceptionalEdges(UnitGraph.java:128)
at soot.toolkits.graph.ExceptionalUnitGraph.initialize(ExceptionalUnitGraph.java:258)
at soot.toolkits.graph.ExceptionalUnitGraph.<init>(ExceptionalUnitGraph.java:159)
at soot.toolkits.graph.ExceptionalUnitGraph.<init>(ExceptionalUnitGraph.java:192)
答案 0 :(得分:0)
在不改变代码行为的情况下移动代码的技术称为Refactoring
,并且在Martin Fowler的书中很好地介绍了。
在您的情况下,我会采取以下多步骤方法:
强烈建议您编写一组测试来首先验证此块的整体功能(如果不是大多数)。然后,在每次更改后运行您的测试以验证您没有改变行为。
您现在看到的是通过以改变行为的方式修改代码文本而产生的行为变化。源代码的安全转换集可能比您之前认为的要小,或者您可能只是犯了一个简单的错误。但是,您正在尝试的工作需要的知识多于StackOverflow样式,问题/答案,格式。这就是我为什么参考这本书的原因。
如果您可以缩小范围,您可能会在将来的重新提交中获得更好的响应。
答案 1 :(得分:0)
似乎移动stmts不起作用。相比之下,完全取代身体
Body originalBody = sm.getActiveBody();
originalBody.setMethod(auxMethod);
auxMethod.setActiveBody(originalBody);
Body newBody = Jimple.v().newBody(sm);
sm.setActiveBody(newBody);
然后在newBody
中重新生成本地人,身份stmts(以及您可能需要的其他stmts)看起来是一种明智的方式。