我想知道是否有办法在出现异常时转储所有局部变量的状态,以便更好地了解导致异常的环境状态。变量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参数)也无法进行代码更改。我看过他们但却找不到任何东西。与此同时,我也会一直在那里搜索;)
答案 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.评估可疑代码并系统地取消注释代码,直到异常发生,反之亦然。
虽然有时候你会发现它很乏味和令人沮丧,但它确实对你的基础有所帮助,因为通过足够的练习,你很快就能够直观地发现错误通常发生的位置(因此在未来的调试中花费的时间更少)