如何获得线条' Java堆栈中的列号

时间:2014-04-30 07:42:15

标签: java stack-trace

在某些语言中,可以在堆栈跟踪中获取行的列号,但在Java中,我们只有行号。

举个例子,我们可以用另一种语言:

Error
    at <anonymous>:2:2
    at Object.InjectedScript._evaluateOn (<anonymous>:641:39)
    at Object.InjectedScript._evaluateAndWrap (<anonymous>:580:52)
    at Object.InjectedScript.evaluate (<anonymous>:495:21)"

虽然这可能是一个糟糕的例子,因为我从浏览器控制台导致错误,但您可以看到列号,这对解决错误非常有帮助。

用Java提供示例(是的,名称已更改):

Caused by: java.lang.IllegalArgumentException: path was null
    at org.jboss.resteasy.specimpl.ResteasyUriBuilder.path(ResteasyUriBuilder.java:362)
    at enterprise.money.service(AbstractSomething.java:88)

这会导致包含

的行88

URI uri = uriInfo.getBaseUriBuilder().path(objectA).path(objectB).build();

使用堆栈跟踪,我无法检查哪个.path调用导致异常。所以我的问题是,是否有任何解决方案可以让我获得该列的参考?

(为了防范一些可能的替代答案,我们需要一个解决方案来获取列号,其他答案,如如何逐步调试或重构每个构建器模式等,将无法回答问题)< / em>的

3 个答案:

答案 0 :(得分:5)

这是不可能的。

您可以通过以这种方式格式化代码来绕过它:

URI uri = uriInfo
           .getBaseUriBuilder()
           .path(objectA)
           .path(objectB)
           .build();

在Oracle Java 8 中,您可以编写

public static void main(String... ignored) {
    List<String> s = new ArrayList<>();
    s.add("hello");

    Predicate<? super String> predicate1 = (t) -> t.length() > 0;
    Predicate<? super String> predicate2 = (t) -> t.length() < 8;
    Predicate<? super String> predicate3 = null;

    List<String> collect = s.stream()
            .filter(predicate1) // 16
            .filter(predicate2) // 17
            .filter(predicate3) // 18
            .collect(Collectors.toList());
}

你得到了

Exception in thread "main" java.lang.NullPointerException
    at java.util.Objects.requireNonNull(Objects.java:203)
    at java.util.stream.ReferencePipeline.filter(ReferencePipeline.java:161)
    at Example.main(Example.java:18)

对于Oracle JDK,这似乎只在Java 8中,而不是Java 7。

答案 1 :(得分:3)

对Java进行逆向工程将非常痛苦。从理论上讲,您可以分析原始来源并找出哪些表达式可能引发此类异常。

如果你有这个问题,你的线很可能太复杂/密集。大多数IDE使得重构表达式以提取部分代码变得非常容易。这样可以更好地解决抛出异常的位置。


这个特定问题的另一个解决方案是使用@NotNull的方法,IDE可以检测哪些参数可以为null,但绝不应该是。

URI uri = uriInfo.getBaseUriBuilder().path(objectA)
                                     .path(/*highlighted*/objectB).build();

IDE可以警告您,您正在将变量传递给无法使用null的方法。如果您这样做,您将更早地获取这些错误并使其更容易修复。 (IDE附带了一些快速修复程序)

注意:一般来说,错误传递的null参数API应该抛出NullPointerException IMHO,但是IllegalArgumentException通常会引起一些不一致的抛出。

正如我所看到的,IllegalArgumentException的一个参数是;

  • 您可能希望应用程序捕获IllegalArgumentException。捕获NullPointerException真的很有气味。
  • 无效null的处理应与其他不正确的参数相同,例如长度为-1

IMHO将null传递给不接受null的方法是编程错误,而不是提供错误输入的问题。

答案 2 :(得分:3)

您无法从堆栈跟踪中获取列。

你可以做的是使用中间变量,这样你就可以在不同的行上调用每个方法:

UriBuilder builder = uriInfo.getBaseUriBuilder();
builder = builder.path(objectA);
builder = builder.path(objectB);
URI uri = builder.build();

这很痛苦,但它可以暂时帮助找到问题,然后你可以把它恢复原状。