0

我只有一个几分钟后挂起的 Web 应用程序。基本上,这是一个用于构建和预览表单的应用程序,非常定制,经过几分钟的密集用户交互后,该应用程序就停止工作了。这意味着,请求已完成并且永远不会返回回复。

我“有点”迷失了,因为我也没有找到任何关于 tomcat 日志和应用程序日志中挂起的线索。应用程序服务器正在运行,因为我正在使用 lambda/psi-probe 并且可以毫无问题地检查任何其他甚至是麻烦的应用程序(探针本身是另一个 Web 应用程序)。

该应用程序使用了 hibernate,它可以正常工作很长时间,最近,为了提高性能(如果你只使用它,hibernate 会注入很多查询)我已经通过 java.sql 标准 api 引入了本机 sql。我小心不要将两者混合使用,它们仅在 jsp 中使用,首先使用 hibernate 检索一些(少数)对象,然后使用 jdbc 使用一些逻辑。在使用 jdbc 之前关闭 Hibernate 会话。

我已经阅读了一些关于数据库连接问题(我已经检查过几次并且数据库服务器运行正常)、死锁或失控线程的内容,在 VisualVM 中使用 VisualVM 进行了检查。

那么,任何人都可以提供有关发现或捕获挂起的线索吗?可以提供一些线索来使用 VisualVM 捕获或捕获假设的失控线程或死锁吗?后者会启发我,因为我只看到等待和运行的线程。

我在 mac osx 和 linux(开发和预生产机器)上使用 tomcat 6.0.21(我总是尝试 7.0.11 并获得相同的结果)java 1.6

任何想法都会受到欢迎,谢谢

威利

4

3 回答 3

1

尝试运行 jconsole(如果在挂起的机器上无法执行此操作,则需要启用远程 JMX,重新启动 JVM 并重现挂起),然后单击 Threads 选项卡并单击 Detect Deadlock . 这可能会提供一些帮助。

正如您所说,其他要使用的东西是 VisualVM 或JCarder

编辑

看到您的评论后,另一件要尝试的事情是:

  1. 启动 JConsole 并连接到挂起的 VM
  2. 导航到 MBeans → com.sun.management → HotSpotDiagnostic → 操作
  3. 将有一个按钮dumpHeap,旁边有两个文本框。在第一个文本框中,输入一个唯一的名称 - 我使用我的首字母和日期之类的名称 - rt20110317。将第二个文本框设置为 true。按下dumpHeap按钮。

这会将堆写入一个大文件。找到该文件并将其加载到Eclipse MAT中。该工具提供了用于查看 VM 状态的各种有用的点点滴滴。甚至还有一些用于查找内存泄漏的向导,如果它是由于相同类型的症状,它们也可能会找到您的 VM 挂起的原因。

于 2011-03-16T15:48:00.947 回答
1

我一直处于类似的情况。问题是某些数据库连接从未返回到连接池。达到限制后,应用程序将冻结,没有异常或错误。你也可能是这种情况。打开连接池中的废弃连接日志记录,您可能想检查是否有任何恶意连接。

于 2011-03-16T16:36:08.720 回答
0

确保关闭任何这样的 JDBC 调用:参考:http: //tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html#Preventing_dB_connection_pool_leaks

这是使用从连接池获得的数据库连接的正确编写代码的示例:

  Connection conn = null;
  Statement stmt = null;  // Or PreparedStatement if needed
  ResultSet rs = null;
  try {
    conn = ... get connection from connection pool ...
    stmt = conn.createStatement("select ...");
    rs = stmt.executeQuery();
    ... iterate through the result set ...
    rs.close();
    rs = null;
    stmt.close();
    stmt = null;
    conn.close(); // Return to connection pool
    conn = null;  // Make sure we don't close it twice
  } catch (SQLException e) {
    ... deal with errors ...
  } finally {
    // Always make sure result sets and statements are closed,
    // and the connection is returned to the pool
    if (rs != null) {
      try { rs.close(); } catch (SQLException e) { ; }
      rs = null;
    }
    if (stmt != null) {
      try { stmt.close(); } catch (SQLException e) { ; }
      stmt = null;
    }
    if (conn != null) {
      try { conn.close(); } catch (SQLException e) { ; }
      conn = null;
    }
  }

"

于 2011-07-13T18:23:40.977 回答