在Exception上转储变量的状态

时间:2012-01-20 16:09:58

标签: java debugging exception

我想知道是否有办法在出现异常时转储所有局部变量的状态,以便更好地了解导致异常的环境状态。变量idsToDump下面在运行时是未知的,我想找出集合中的值导致NPE的状态。

示例:

public static void main(String[] args) {
    HashMap<Integer, String> employees = new HashMap<Integer, String>();
    employees.put(1, "James");

    Integer[] idsToDump = new Integer[] { 1, 2, 3 };
    for (Integer employeeId : idsToDump) {
        String name = employees.get(employeeId).toLowerCase();
        System.out.println(name + " is employee number: " + employeeId);
    }

}

输出:

james is employee number: 1
Exception in thread "main" java.lang.NullPointerException

问题: 是否有一些JVM参数可以传递以转储有关局部变量当前状态的信息?即我们得到

java.lang.NullPointerException

和(这是我之后的部分)

values: employeeId=2

我希望能够在客户端站点上执行此操作,因此无法访问Eclipse或调试工具(仅查找JVM参数)也无法进行代码更改。我看过他们但却找不到任何东西。与此同时,我也会一直在那里搜索;)

6 个答案:

答案 0 :(得分:2)

最简单的方法是在调试器中运行此代码并逐步执行。如果您无法调试代码,那么您可以使用try / catch块并在其外部设置employeeId,如:

int debugEmployeeId = -1;
try {
    Integer[] idsToDump = new Integer[] { 1, 2, 3 };
    for (Integer employeeId : idsToDump) {
        debugEmployeeId = employeeId;
        ...
} catch (Exception e) {
    throw new Exception("Missing employeeId = " + Integer.toString(debugEmployeeId));
}

答案 1 :(得分:2)

我遇到了一个商业产品,通过简单地使用启动-agentlib JVM代理参数来实现这一点。我还没有使用它,但打算试一试,因为它看起来很有希望。

https://www.takipi.com/product

任何人都有使用此产品的经验吗?

答案 2 :(得分:1)

考虑到你的所有限制,除了jdb之外,我不能推荐任何其他内容。解雇那个坏孩子并开始逐行逐步完成客户端代码。我知道你说 没有 调试工具,但除非它们只是一个JRE环境,否则你应该已经安装了jdb。

答案 3 :(得分:1)

虽然您已经提到您无法进行任何代码更改,但这里提示仍然可以进行代码更改:获取有关异常的更多信息的方便工具是方法“printStackTrace”抛出异常对象。你可能想要使用这样的东西。


try {
...
}
catch ( Exception e ) {
  System.out.println( "Exception occured! Reason: " + e.printStackTrace() );
}

答案 4 :(得分:0)

您最好的选择afaik是旧的手动方式:使用某种日志记录(无论是Log4J,还是stdout),并通过catch块显式记录您感兴趣的变量。

答案 5 :(得分:0)

与Thomas一样,我不知道任何可以转储变量的方法。但是,我相信您希望这样做是为了帮助您进行调试。以下是一些简单的方法,我只使用控制台调试代码:

1.学习异常发生时读取堆栈跟踪。它为您提供了许多可能导致异常的信息。如果stacktrace指向的特定行似乎没有任何错误,则跟踪代码并查看它是否是导致异常的先前对象。例如(使用一些示例代码和方法):

Book book = null;
Bookshelf bookshelf = new Bookshelf();
bookshelf.add(book);
bookshelf.getBooks();

这样的东西会导致NPE堆栈跟踪指向bookshelf,但实际上它是导致NPE的book

2.打印出您怀疑导致NPE的变量。

for (Integer employeeId : idsToDump) {
  System.out.println(employeeId);
  String name = employees.get(employeeId).toLowerCase();
  System.out.println(name + " is employee number: " + employeeId);
}

您的输出将是:

1
2

然后你会知道2导致了NPE。

3.评估可疑代码并系统地取消注释代码,直到异常发生,反之亦然。

虽然有时候你会发现它很乏味和令人沮丧,但它确实对你的基础有所帮助,因为通过足够的练习,你很快就能够直观地发现错误通常发生的位置(因此在未来的调试中花费的时间更少)