收集 Thread Dump 当 JVM 运行时,您可以定期收集其 Thread Dump,通常相隔约 5 至 10 秒。 利用这些信息,您也许能找到递归代码并将其改正。为了收集 Thread Dump,您需要对 Java 进程 ID (PID) 执行下列命令: Unix 型平台:
- 在预计崩溃之前执行 kill -3。
- kill -3 <jvm-pid> 转储 java 线程。
Windows 平台:
- 对 JVM PID 执行 kill .3。
- 还可以在 JVM 正在运行的窗口中执行 <CTRL>
<BREAK>。
对于 JRockit JVM:
- 对所有平台上的 JRockit JVM 执行上述命令。
确保您在根 java 进程上执行此命令。
- 若要获得进程的树状结构(父 - 子 ASCII 图),可使用 --forest 选项。
例如,若要查找由用户“usera”启动的进程,可执行 ps -lU usera -.forest
返回页首
停止 JVM 进行 Thread Dump 您可以设置下列标志,以便在生成核心文件之前进行服务器的 Thread Dump,以得到此时刻的线程状态:
Sun JVM 在 SUN JVM 上,该选项是 -XX:+ShowMessageBoxOnError(在 SUN 网站上没有正式记载)。当 JVM 崩溃时,程序将提示:您想要调试此问题吗?然后您可以进行 JVM Thread Dump。
JRockit JVM 当发布 JRockit 的 8.1 SP2 版 Service Pack 时,将在该版本中提供相应的选项。该选项在 JRockit 中是 -Djrockit.waitonerror。
返回页首
递归性 JSP 错误页和标记 有一些用户已使用 JSP 的下列信息解决了递归性问题:
JSP 错误页:
- 在您的 jsp_error 页面内检查,查看是否带有标记 <%@ page errorPage="jsp_error"%>,因为这将导致无限递归。
- 去除此标记,并简单打印可能发生的任何异常的堆栈跟踪。
这样可以在错误页面中找到问题。
- 解决此问题之后,就可以查看发送到此页面上的原始错误。
JSP 标记:
- 通过检查确定是否有错误的 jsp/servlet login/auth/error 报告代码。
- 如果此代码有问题,则纠正此问题也就解决了递归以及崩溃问题。
WebLogic JSP 表单确认标记:
- 如果您正在使用 WebLogic JSP 表单验证标记,确保 <wl:form>的 action 属性没有设成包含 <wl:form> 标记的页面,否则将创建一个无限循环而导致堆栈溢出异常。
返回页首
调整堆栈大小
另一个可能的解决方法是对 JVM 采用 -Xss参数来增加线程堆栈的大小。但是,如果这是一个递归调用,这样做将不会有帮助,而只会延迟发生不可避免的问题。每个
Java 线程有两个堆栈:一个用于 Java 代码,一个用于 C 代码。此选项可将线程中 C 代码所使用的最大堆栈大小设置为指定的值。有关
-Xss标志的完整定义,请参见以下网址的“Non-Standard
Options”部分:http://java.sun.com/j2se/1.3/docs/tooldocs/solaris/java.html
返回页首
Sun 的已知问题
另一个 StackOverFlow问题会产生于来自
java.util 包的 getProperty
调用中。如果发现一个对 java.util.Properties.getProperty(Properties.java:475)的递归调用,这将导致出现
java.lang.StackOverflowError。此问题出现在所有的
JDK 和版本中(1.3.1 或 1.4.1)。这是 JDK 中 Properties()类构造器的问题。Sun
记录了一个错误报告 #4906193:
在代码中不执行此行:
Properties p = new Properties(System.getProperties());
而执行:
Properties p = new Properties();
p = System.getProperties();
以避免所发现的递归调用堆栈跟踪。
此问题在一段时间内出现在特定的 Web 应用程序中(在应用程序的登录部分),且不易向下跟踪。下面是被注释掉的错误行的示例代码。如果在一个简单的独立 java 客户端中使用了该行而未使用之后的两行(本质上它们执行同样的功能),那么您将看到递归的堆栈跟踪。
|