如何诊断哪个字段/方法导致NullPointerException

时间:2011-07-22 15:24:39

标签: java nullpointerexception javaagents

假设你有类似的Java代码:

getPerson().getParent().getSiblings().first().getName()

你在那一行得到一个NullPointerException。你怎么知道哪一个是空的?您可以调试它并检查每个呼叫,或者您可以暂时将链接拆分为多行。

但是,我记得刚才看到一个开源项目会运行,我认为它是一个javaagent,它会为NullPointerException提供更好的堆栈跟踪,它给出了返回null结果的方法调用。不幸的是我似乎无法找到它。有谁知道怎么做,或者它是什么工具?

5 个答案:

答案 0 :(得分:1)

恕我直言,当你没有放入可能引发npe的一行方法时,这是一种更好的风格。然后你没有这样的问题:)甚至把每个调用放在一行(但是像method1()\ n.method2()那样的一个相同的指令)并不是一个好主意。简单的代码重新格式化可以将它们放回一行。

如果方法可能返回null,那么每次都应该检查返回值。如果该方法不应返回null,则getter应包含一个检查并抛出异常(IllegalStateException?)而不是返回null。

您可以使用AspectJ和load-time veave(使用javaagent)向现有代码添加此类检查。

例如:

/** Throw Error if a method for creating a Point returns null */
after () returning (Point p) : 
    call(Point+ SubPoint+.create(..)) {
    if (null == p) {
        String err = "Null Point constructed when this (" 
            + thisJoinPoint.getThis() 
            + ") called target (" 
            + thisJoinPoint.getTarget() 
            + ") at join point (" 
            + thisJoinPoint.getSignature() 
            + ") from source location (" 
            + thisJoinPoint.getSourceLocation()
            + ") with args ("
            + Arrays.asList(thisJoinPoint.getArgs())
            + ")";
        throw new Error(err);
    }
}

答案 1 :(得分:1)

有趣。

一个人可以有一个空父母吗? (不要在性生殖中有两个父母吗?)

如果你是独生子女怎么办? getSiblings()应该返回什么? null,或者更好的是,一个空集合?

如果您没有名字怎么办? Sting或Madonna是名字还是姓?如果是的话,姓氏会返回什么?

这里真正的问题是设计。你没有想过在nulls的情况下该怎么做。最好搞清楚。

答案 2 :(得分:0)

理想情况下,您可以将每个方法的返回值分配给变量,这样您就可以检查这些变量;这就是编译器内部使用临时变量所做的事情。

如果您不想重写,可以在该行上设置断点,然后为每个函数添加一个监视(最简单),或者(如果您的IDE支持它)键入每个函数1-at - 进入“即时”窗口的时间,看看会发生什么。

答案 3 :(得分:0)

我的观点是,这是一个简洁的代码而不是可维护代码的问题。链接功能可能会使代码看起来更干净,但可能会导致代码库长期难以维护。如果您将操作分开,则可能会有更长的功能,但追踪错误应该更加容易。

答案 4 :(得分:0)

我认为有些人可能会比OP要求的更复杂

您所要做的就是将每个链式方法放在自己的行上。

getPerson()
.getParent()
.getSiblings()
.first()
.getName();

您将得到正确的行号,它将指示NPE的哪个方法(前一行返回null)。

是的,你可以做各种强大的NPE检查,但在一天结束的时候有时候你需要完成任务并且可能没有预期null,所以不要用其它错误处理来覆盖它。

您还可以通过在对象及其子对象上添加validation annotations来防止这种情况发生。验证对象然后继续遍历对象树。这对我来说过去很有用。这将为您提供更好的自动可重用错误处理。另外,您正在记录哪些方法可以返回null。

说它的糟糕设计支持链接我不认为是公平的,因为最流行的Javascript(jQuery)库之一一直使用它(是的,它有时会返回null / undefined值)。