在Exception上转储变量的状态

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

例:

 public static void main(String[] args) { HashMap employees = new HashMap(); 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参数)也无法进行代码更改。 我看过他们但却找不到任何东西。 与此同时,我也会一直在那里搜索;)

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

最简单的方法是在调试器中运行此代码并逐步执行它。 如果您无法调试代码,那么您可以使用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)); } 

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

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

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

https://www.takipi.com/product

有人有这个产品的经验吗?

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

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

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

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

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

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.评估可疑代码并系统地取消注释代码,直到exception发生,反之亦然。

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