热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

将所有语句从一种方法移动到另一种方法-Movingallstatementsfromonemethodtoanother

SoIhaveaMethod所以我有一个方法publicmodifiersFoofoo(Barbar){blah;blah;veryInterest

So I have a Method

所以我有一个方法

public modifiers Foo foo(Bar bar){
    blah;
    blah;
    veryInterestingStmt;
    moreBlah();
    return XYZ;
}

I now want to split this method s.t. everything in its body is extracted into a separate method (programmatically).

我现在想要分割这个方法s.t.其身体中的所有内容都被提取到一个单独的方法中(以编程方式)。

I.e.

public modifiers Foo foo(Bar bar){
    return trulyFoo(bar);
}

public modifiers Foo trulyFoo(Bar bar){
    blah;
    blah;
    veryInterestingStmt;
    moreBlah();
    return XYZ;
}

How do I do that, though?

但是我该怎么做呢?

The naive

天真

private void fracture(SootMethod sm) {

        SootClass sc = sm.getDeclaringClass();

        String auxMethodName = sm.getName() + FRACTURE_SUFFIX;

        Type auxReturnType = sm.getReturnType();
        ListauxParamTypes = 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 units = body.getUnits();
        PatchingChain auxUnits = auxBody.getUnits();

        Iterator 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}
        }
    }
}

Doesn't work. If I run, say

不起作用。如果我跑,说

DirectedGraph dg = new ExceptionalUnitGraph(auxMethod.getActiveBody());

I get a

我得到了

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.(ExceptionalUnitGraph.java:159)
    at soot.toolkits.graph.ExceptionalUnitGraph.(ExceptionalUnitGraph.java:192)

2 个解决方案

#1


0  

The technique of moving code without altering the behavior of the code is called Refactoring and is nicely covered in a book by Martin Fowler.

在不改变代码行为的情况下移动代码的技术称为重构,并在Martin Fowler的书中很好地介绍。

In your case, I would take the following multi-step approach:

在您的情况下,我将采取以下多步骤方法:

  1. Stand up a "do nothing" function in the function you wish to split, just above the lines of code you wish to move.
  2. 在要分割的功能中站起来“无所事事”功能,就在您想要移动的代码行的上方。
  3. Move one or two of those lines of code from the surrounding function int the "do nothing" function, splitting the function, but having the split be a nested call.
  4. 将这些代码行中的一行或两行从周围的函数移动到“do nothing”函数中,拆分函数,但将split拆分为嵌套调用。
  5. Move the split function up (or down) to the edge of the block in the surronding function.
  6. 将分割功能向上(或向下)移动到surronding功能中的块边缘。
  7. Move teh slpit function out of the block, placing new calls to it either prior to every call of the original function, or after every call of the original function. Note that you may have to rework the handling of return parameters, depending on the details.
  8. 将slh slpit函数移出块,在每次调用原始函数之前或每次调用原始函数之后对其进行新调用。请注意,您可能需要重新处理返回参数,具体取决于详细信息。

It is strongly suggested that you write a set of tests to validate some, if not most, of the overall functionality of this block first. Then, after each change run your tests to verify that you didn't change behavior.

强烈建议您编写一组测试来首先验证此块的一些(如果不是大多数)整体功能。然后,在每次更改后运行您的测试以验证您没有更改行为。

What you are seeing now is a change in behavior which came about by modifying the text of the code in such a manner that it did change behavior. The set of safe transformations of source code is likely smaller than you previously believed, or maybe you just made a simple error. However, the work you are attempting requires more knowledge than can be expressed in a StackOverflow style, question / answer, format. That's why I made the book reference.

你现在看到的是行为的改变,这是通过修改代码文本以改变行为的方式而产生的。源代码的安全转换集可能比您之前认为的要小,或者您可能只是犯了一个简单的错误。但是,您正在尝试的工作需要的知识多于StackOverflow样式,问题/答案,格式。这就是我写这本书的原因。

If you can narrow the scope, you might get a better response in a future resubmission.

如果您可以缩小范围,则可能会在将来的重新提交中获得更好的响应。

#2


0  

It seems that moving stmts just doesn't work. In contrast, completely replacing the body

移动stmts似乎不起作用。相比之下,完全取代了身体

        Body originalBody = sm.getActiveBody();
        originalBody.setMethod(auxMethod);
        auxMethod.setActiveBody(originalBody);
        Body newBody = Jimple.v().newBody(sm);
        sm.setActiveBody(newBody);

and then regenerating the locals, identity stmts (and other stmts you may need) in the newBody looks like a sensible way to go.

然后在newBody中重新生成本地人,身份stmts(以及你可能需要的其他stmts)看起来是一种明智的方式。


推荐阅读
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
  • 本文详细介绍了 Apache Jena 库中的 Txn.executeWrite 方法,通过多个实际代码示例展示了其在不同场景下的应用,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 本文详细介绍了Java中org.eclipse.ui.forms.widgets.ExpandableComposite类的addExpansionListener()方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。这些示例来源于多个知名开源项目,具有很高的参考价值。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
author-avatar
大师傅放放风_769
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有