如何调试 Java 应用程序中的静默故障?
我正在尝试调试我的 Java 应用程序中的一个问题,该问题不会引发错误,不会引发异常,甚至不会使应用程序崩溃(似乎故障发生在单独的线程中)。
问题似乎出在对库函数的调用内部(如果重要的话,它是 JAXBContext.newInstance(String) )。 程序将到达调用之前的那一行,但不会到达调用之后的那一行。 我的 catch
块未输入,程序只是继续运行。
当尝试对通过 Struts 传入的 Web 请求呈现 XML 响应时,会出现此问题。 请求已被处理,代码应该封送响应对象。 客户端立即收到响应(因此代码似乎没有陷入循环),但它只是空的。
我在有问题的行之前设置了一个断点,但调试器只是在它上面运行,我不知道为什么。
我正在使用 eclipse,应用程序在 OSGi 容器 (Apache Felix) 内运行,该容器是使用 -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y
启动的。 然后,我在 Eclipse 中使用“远程 Java 应用程序”的调试设置来连接调试器。
解决此类问题的技术是什么?
I'm trying to debug a problem in my Java application that throws no errors, no exceptions and doesn't even crash the app (it seems the failure happens in a separate thread).
The problem seems to be inside a call to a library function (it's JAXBContext.newInstance(String)
if that matters). The program will reach the line just before the call, but not the one just after it. My catch
blocks are not entered and the program just continues to run.
The problem happens while trying to render an XML response to a web request that came in via Struts. The request has been handled and the code should marshal the response object. The client gets a response right away (so the code doesn't seem to hang in a loop), but it's just empty.
I have set a breakpoint just before the problematic line but the debugger just runs over it, I haven't a clue why.
I'm using eclipse and the application runs inside an OSGi container (Apache Felix) that was started with -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y
. From within Eclipse I then use the Debug settings for "Remote Java application" to connect the debugger.
What are techniques to get at such a problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
可能是一个显而易见的问题,但你确定你正在捕获 Throwable 吗? 未经检查的异常很容易导致有问题的线程死亡(假设调用堆栈中你上面的人也没有捕获它。)
由于你在启动时使用调试参数挂起虚拟机,我假设你已经确认调试器是正确安装。 您说调试器跳过调用的事实非常可疑。 您能够在此应用程序中命中断点吗? 这个班级又怎样呢? 在这个线程中呢?
在没有调试器的情况下,如何缩小有问题的行范围? println/调试到文件?
您可以粘贴相关方法的代码片段吗?
您可以通过在问题发生之前创建第二个线程并将其连接到您认为即将死亡的线程来确认线程即将死亡的理论。 然后,当有问题的线程退出时,将调用第二个线程的 run() 方法,并且您知道它死了(但仍然不知道为什么。)
回答您的一般问题,当我在 Java 应用程序中遇到错误时我无法在调试器中重现(由于各种原因,这种情况时常发生),我使用 sysout printlns 或输出到文件逐步修改我的代码。 如果有必要,我还可以修改我的代码正在调用的代码。 如果您没有要调用的代码的源代码,您可以尝试使用众多 BCI 框架之一将字节代码注入到相关方法中。 这是一个乏味的过程,但只是偶尔发生。
Probably an obvious question, but are you sure you are catching Throwable? An unchecked exception could easily cause the thread in question to die (assuming no one above you in the call stack is catching it either.)
Since you are suspending the VM on startup with your debug arguments, I assume you have confirmed that the debugger is attaching correctly. The fact that you say the debugger skips right past the call is very suspect. Are you able to hit any breakpoints in this application? What about in this Class? What about in this thread?
How did you narrow down the line in question without the debugger? println/debugging to a file?
Can you paste a code snippet of the method in question?
You could confirm the theory that the thread is dying by creating a second thread before the problem occurs and joining it to the thread you think is dying. Then the second thread's run() method would be invoked when the thread in question exits, and you'd know it died (but would still not know why.)
In answer to your general question, when I have a bug in a Java app that I can't reproduce in the debugger (which happens from time to time for various reasons), I incrementally modify my code with sysout printlns or output to files. If necessary, I may also modify the code my code is invoking. If you don't have the source code to the code you are invoking, you can try one of the many BCI frameworks to inject your byte code into the methods in question. It's a tedious process, but only happens occasionally.
您可以尝试获取 Thread Dump - 这会告诉您是否有任何方法正在阻塞(例如等待用于输入)。 [编辑:重新阅读您原来的问题,获取线程转储可能不会有帮助,因为它看起来实际上没有任何阻塞。 但我将其留在这里,因为我发现它在许多其他情况下都很有用!]
如果您认为错误发生在另一个线程中,您还可以设置 UncaughtExceptionHandler 尝试捕获它。
You could try getting a Thread Dump - that will tell you if any methods are blocking (e.g. waiting for input). [Edit: re-reading your original question, getting a thread dump probably won't help as it looks like nothing is actually blocking. But I'm leaving it here as I find it useful in many other situations!]
If you think the error is happening in another thread you could also set an UncaughtExceptionHandler to try and catch it.
如果您确定问题出在该方法中的某个位置,您可以尝试查看 JAXB 源代码。
编辑:
好吧,如果情况变得非常糟糕,您可以使用调试工具构建自己的私人副本。 我希望你不必诉诸于此。
If you're sure the problem is somewhere within that method, you could try looking at the JAXB source code.
EDIT:
Well, if it gets really bad you can build your own private copy with debugging instrumentation. I hope you won't have to resort to that.
也许在调用内部发生了无限循环,这就是为什么您无法进一步进行的原因 - 但这可能不会导致崩溃(除非每个循环中都使用内存)。
perhaps inside the call there is an infitite loop happening and this is why you get no further - but this might not cause a crash (unless memory is being used in each loop).