【问题标题】:Debugging a Java program running from Tomcat (JSP)调试从 Tomcat (JSP) 运行的 Java 程序
【发布时间】:2011-05-04 11:53:15
【问题描述】:

我不知道为什么我从来没有发现自己必须使用调试器来单步调试我的程序并查看发生了什么,可能是因为我习惯于使用 PHP 等解释性语言,这样添加起来变得非常容易调试代码 (print_r) 并实时查看更改。

但是对于这个新的 Java 项目,我觉得我必须学习正确的调试方法。

所以这个不是我写的程序在 Tomcat 上运行并使用基本的 JSP。问题是,当我尝试访问特定的 JSP 页面时,它会抛出异常并给我所发生事件的堆栈跟踪:

org.apache.jasper.JasperException: java.lang.NullPointerException
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:503)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:433)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:363)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:306)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.sgrp.singer.filters.SingerLoginFilter.doFilter(SingerLoginFilter.java:128)

如何使用 JDB 等工具逐步执行我的程序?我不能真正单步执行一个特定的类,因为我需要模仿我的 JSP 正在做什么......我想通过命令行来做这件事,而不使用 IDE。

【问题讨论】:

    标签: java debugging jsp tomcat jdb


    【解决方案1】:

    首先,必须使用某些参数启动 java 才能插入调试器:

    -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n
    

    是用于我们目的的参数。之后,您使用 IDE 并远程连接调试器。您对一段代码设置断点(请确保本地文件和远程程序的版本完全相同)并生成错误。您也可以为未捕获的异常设置断点。

    作为提示:您可以更改引用的错误捕获 JSP(对于我们来说是 error.jsp),以不仅显示捕获的异常的堆栈跟踪(ex.getStracktrace),还显示导致堆栈跟踪(ex.getCause( ).getStacktrace())。这可能有助于识别更高级别的异常原因。

    编辑:对不起,如果没有 IDE,这是人类可能无法做到的信息溢出。 Tomcat 应用程序在架构级别上很复杂,需要在多个不同的类之间切换以实现最简单的请求。

    【讨论】:

    • 我知道 IDE 提供了这个......没有 IDE 是否可能?
    • 是的,当然。像 Eclipse 这样的 IDE 只在后台使用普通的 java 调试器。集成调试器使用的每个函数在普通 JDK 的命令行调试器中都有一个等效函数。你应该检查documentation for jdb。我的例子中的端口是 8000,所以绑定应该去那里。
    • 如果没有 IDE,您可以使用 jdb 进行一些调试。 jdb -attach 0.0.0.0:8000 2>&1 |tee java_debug.log 尝试使用命令:help、threads、trace go methods thread ...参考jdb手册docs.oracle.com/javase/7/docs/technotes/tools/windows/…>
    【解决方案2】:

    另一种解决方案可能比将调试器挂钩到 Tomcat 更容易使用:

    首先,看一下调用堆栈。在底部,您会看到名为 org.sgrp.singer.filters.SingerLoginFilter 的类。问题出在方法doFilter 的第128 行。

    第一行是org.apache.jasper.JasperException: java.lang.NullPointerException。这意味着您在上述类的第 128 行使用了一个值为 null 的对象。

    查看该代码以找出可能出现的问题。此外,在您的代码中添加一些打印/记录语句。

    调试应该是你最后的手段。只需查看堆栈跟踪,您就可以收集大量信息。

    【讨论】:

    • 是的,但是 JDB 有没有一种方法可以进入该 SingerLoginFilter 类并运行该函数 doFilter 并在该行上设置一个断点,这样我就可以在它被调用之前准确地看到它正在获取什么值等。
    • @Luca:我没有亲自使用过JDB调试Tomcat。也许这个链接会帮助你:mo.morsi.org/blog/node/219。从那篇文章中,您需要“停在 org.sgrp.singer.filters.SingerLoginFilter:128”。尝试谷歌搜索“jdb tomcat”
    【解决方案3】:

    可以使用 JDB,但它不是我的首选。

    这是一个很好的解释如何使用它: http://www.javaworld.com/javaworld/javaqa/2000-06/04-qa-0623-jdb.html

    您需要记住在编译文件并设置 Tomcat 时包含调试信息,以便能够连接到它,这是字符串,如其他帖子所述:

    -Xdebug -Xnoagent -Djava.compiler=NONE-Xrunjdwp:server=y, transport=dt_socket,address=8000,suspend=y

    8000 可以替换为任何其他数值。它基本上告诉 jvm 在该端口上侦听调试器。

    现在会发生什么,tomcat 会启动,但会自行挂起并等待调试器附加,然后再继续。

    启动 JDB 并附加:

    jdb -attach localhost:8000

    在这里,如果tomcat运行在不同的机器上,localhost可以替换为运行的位置,8000可以替换为你在tomcat中设置jvm的任何端口。

    现在可以调试了,在jdb中输入help就可以看到调试说明了。

    【讨论】:

      【解决方案4】:

      我一直使用 eclipse 调试器,要么在 eclipse 中运行 tomcat,要么将 eclipse 连接到一个单独的,但 eclipse 本地的 jboss 服务器。

      像梦一样工作,无需更改 jvm 设置或任何东西。

      【讨论】:

        猜你喜欢
        • 2013-02-07
        • 1970-01-01
        • 2013-05-11
        • 2015-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-26
        相关资源
        最近更新 更多