0

我需要以编程方式检测给定方法是否可能返回 null。

检查器框架似乎能够做到这一点,但仅限于带注释的源代码。我需要它的字节码。具体来说,我需要验证以下声明:

Method x.y.Z#foo() cannot return null.

我只有 xyZ 类的字节码

你知道有什么工具可以支持吗?

在一般情况下这甚至可能吗?据我所知,它不等同于停机问题,因为不需要找出程序的确切路径。例如在

Foo bar() {
    if (cond) { return null; } else { return new Foo(); }
}

分析工具不需要关心cond,只要注意至少在所有可能的路径中,null返回一个就足够了,因此可以拒绝 bar 不能返回 null 的说法。

注意:我会接受误报,例如,cond可能是公正false的,分析工具仍然可以声称 bar() 可以返回 null(这相当于说我们不能在一般情况下证明cond必须为真)。

4

2 回答 2

2

我不知道有什么工具可以做到这一点,但如果误报是可以接受的,那么我认为这是可能的。

从方法返回的值最终将来自以下之一

  • 方法中的常量
  • 提供的参数
  • 一个领域
  • 另一个 java 方法调用的结果
  • 本机调用的结果
  • 构造函数调用
  • 一个我忘记的来源

如果您假设任何字段或参数可能为 null,并且任何本机调用都可能返回 null,那么每个方法都可以标记为可能返回 null,如果

  • 方法的流程可以返回一个空常量
  • 方法的流程可以返回一个字段
  • 方法的流程可以返回一个参数值
  • 方法的流程可以返回原生调用的结果
  • 方法的流程可以从一个本身可以返回null的方法返回一个值

但是,它可能没有用,因为它可能会产生高比例的误报(您必须有一些可接受的最大百分比,否则您可以使用简单返回 true 的方法来满足您的要求)。

您也许可以添加额外的启发式方法来减少被视为空的字段/参数/方法的数量。

ASM 树 api 提供了您尝试和实现它所需的所有构建块,包括流分析。

于 2013-08-09T14:39:31.570 回答
1

想到了两种可能:

  • 使用查找错误。以 NP 开头的错误模式会对此进行检查,例如:
    • NP_LOAD_OF_KNOWN_NULL_VALUE
    • NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE
    • NP_NULL_ON_SOME_PATH_MIGHT_BE_INFEASIBLE

或者,您可以为此构建自己的错误模式检查...

  • 使用 Eclipse 检查器中的构建。如果你去 Preferences\Java\Compiler\Errors/Warnings 有一个专门的部分(空分析)。您可以将这些设置更改为警告或错误...

[更新]

如果您想以编程方式执行此操作(如 findbugs)并使用字节码库来执行此操作:

  • 具有类似 DOM 的 API 的BCEL
  • 具有类似 SAX 的 API 的ASM 。此处提供教程、用户指南和参考文档

从我所阅读和听到的内容来看,ASM 似乎是一个不错的选择。如果我没记错的话 findbugs 也切换到 ASM(但是里面还有一些 bcel 吗?)。为了不从头开始,您可以将 findbugs 与您/他们的检测器一起使用并将其用作库。因此,您调用他们的错误检测功能并以编程方式启动它,然后分析返回值。我会在 findbugs 邮件列表中询问更多详细信息。

[Update2] 这个可能正在做你需要的事情 - 所以你应该联系他......

于 2013-08-12T07:40:00.950 回答