热门标签 | 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)看起来是一种明智的方式。


推荐阅读
  • 在Cisco IOS XR系统中,存在提供服务的服务器和使用这些服务的客户端。本文深入探讨了进程与线程状态转换机制,分析了其在系统性能优化中的关键作用,并提出了改进措施,以提高系统的响应速度和资源利用率。通过详细研究状态转换的各个环节,本文为开发人员和系统管理员提供了实用的指导,旨在提升整体系统效率和稳定性。 ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • 在处理 XML 数据时,如果需要解析 `` 标签的内容,可以采用 Pull 解析方法。Pull 解析是一种高效的 XML 解析方式,适用于流式数据处理。具体实现中,可以通过 Java 的 `XmlPullParser` 或其他类似的库来逐步读取和解析 XML 文档中的 `` 元素。这样不仅能够提高解析效率,还能减少内存占用。本文将详细介绍如何使用 Pull 解析方法来提取 `` 标签的内容,并提供一个示例代码,帮助开发者快速解决问题。 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 原文网址:https:www.cnblogs.comysoceanp7476379.html目录1、AOP什么?2、需求3、解决办法1:使用静态代理4 ... [详细]
  • 实验九:使用SharedPreferences存储简单数据
    本实验旨在帮助学生理解和掌握使用SharedPreferences存储和读取简单数据的方法,包括程序参数和用户选项。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 大类|电阻器_使用Requests、Etree、BeautifulSoup、Pandas和Path库进行数据抓取与处理 | 将指定区域内容保存为HTML和Excel格式
    大类|电阻器_使用Requests、Etree、BeautifulSoup、Pandas和Path库进行数据抓取与处理 | 将指定区域内容保存为HTML和Excel格式 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • 【问题】在Android开发中,当为EditText添加TextWatcher并实现onTextChanged方法时,会遇到一个问题:即使只对EditText进行一次修改(例如使用删除键删除一个字符),该方法也会被频繁触发。这不仅影响性能,还可能导致逻辑错误。本文将探讨这一问题的原因,并提供有效的解决方案,包括使用Handler或计时器来限制方法的调用频率,以及通过自定义TextWatcher来优化事件处理,从而提高应用的稳定性和用户体验。 ... [详细]
  • 出库管理 | 零件设计中的状态模式学习心得与应用分析
    出库管理 | 零件设计中的状态模式学习心得与应用分析 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • 在使用 Qt 进行 YUV420 图像渲染时,由于 Qt 本身不支持直接绘制 YUV 数据,因此需要借助 QOpenGLWidget 和 OpenGL 技术来实现。通过继承 QOpenGLWidget 类并重写其绘图方法,可以利用 GPU 的高效渲染能力,实现高质量的 YUV420 图像显示。此外,这种方法还能显著提高图像处理的性能和流畅性。 ... [详细]
  • 分享一款基于Java开发的经典贪吃蛇游戏实现
    本文介绍了一款使用Java语言开发的经典贪吃蛇游戏的实现。游戏主要由两个核心类组成:`GameFrame` 和 `GamePanel`。`GameFrame` 类负责设置游戏窗口的标题、关闭按钮以及是否允许调整窗口大小,并初始化数据模型以支持绘制操作。`GamePanel` 类则负责管理游戏中的蛇和苹果的逻辑与渲染,确保游戏的流畅运行和良好的用户体验。 ... [详细]
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社区 版权所有