【问题标题】:Best practice for detecting changes to functions in Scala programs?检测Scala程序中函数更改的最佳实践?
【发布时间】:2011-09-23 15:05:49
【问题描述】:

我正在研究一种基于 Scala 的脚本语言(内部 DSL),它允许用户在 Scala 脚本文件中定义多个数据转换函数。由于这些功能的应用可能需要几个小时,我想将结果缓存在数据库中。 用户可以更改转换函数的定义,也可以添加新函数。但是,然后用户使用稍微修改的脚本重新启动应用程序,我只想执行那些已更改或添加的功能。问题是如何检测这些变化?为简单起见,我们假设用户只能修改脚本文件,以便可以假设对未在此脚本中定义的内容的任何引用都没有改变。

在这种情况下,检测此类用户定义函数的更改的最佳做法是什么?

直到现在我还想:

  • 根据函数定义的源代码解析脚本文件并计算指纹
  • 在运行时获取每个函数的字节码并根据这些数据构建指纹
  • 将函数应用于一些测试数据并计算结果的指纹

但是,这三种方法都有其缺陷。

  • 为 Scala 编写解析器以提取函数定义可能需要相当多的工作,特别是如果您想检测间接影响函数行为的更改(例如,如果您的函数调用脚本中定义的另一个(已更改)函数) .
  • 字节码分析可能是另一种选择,但我从未使用过这些库。因此我不知道他们是否能解决我的问题以及他们如何处理 Java 的动态绑定。
  • 使用示例数据的方法绝对是最简单的方法,但缺点是如果不同的用户定义函数为我的测试数据返回相同的结果,它们可能会意外地映射到相同的指纹。

有人对这些“解决方案”之一有经验吗?或者可以向我推荐一个更好的解决方案?

【问题讨论】:

  • 为什么要编写自己的 Scala 解析器?为此,使用官方 Scala 编译器很容易。此外,还有一个用于扩展编译器的 API。也许可以保存函数的 AST 并稍后将其与新数据进行比较。
  • 谢谢,我去看看。
  • 为每个用户的脚本/函数使用一个 scala 类(lats 说 smthng 扩展 Callable)。然后,您将拥有一组 JVM 类文件(类本身及其下面的所有闭包),并且您将仅为此类文件计算签名(例如 md5),而无需任何字节码魔术。

标签: java scala bytecode


【解决方案1】:

第二个选项看起来并不难。比如用Javassist库获取方法的字节码就这么简单

CtClass c = ClassPool.getDefault().get(className);
for (CtMethod m: c.getDeclaredMethod()) {
    CodeAttribute ca = m.getMethodInfo().getCodeAttribute();
    if (ca != null) { // i.e. if the method is not native
        byte[] byteCode = ca.getCode();
        ...
    }
}

因此,只要您假设您的方法的结果仅取决于该方法的代码,那么这非常简单。

更新: 另一方面,由于您的方法是用 Scala 编写的,它们可能包含一些闭包,因此它们的部分代码驻留在匿名类中,您可能需要以某种方式跟踪这些类的使用情况。

【讨论】:

  • Javassist 似乎是一个不错的库,用于获取方法的字节码等。不幸的是,正如您已经注意到的,这对于 Scala 程序通常是不够的。我认为我需要对我的问题进行更复杂的字节码分析,其中还包括对控制流的分析。 ASM 库 (asm.ow2.org) 似乎提供了这样的功能。我去看看。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-13
  • 2017-12-19
  • 2014-11-18
  • 2011-03-26
  • 2016-09-12
  • 1970-01-01
  • 2016-08-09
相关资源
最近更新 更多