【问题标题】:Why does Java code slow down in debugger?为什么 Java 代码在调试器中会变慢?
【发布时间】:2010-02-03 21:47:52
【问题描述】:

一些 CPU 密集型例程在通过调试器运行时会显着变慢。为什么是这样?

目前我只是使用 IntelliJ 来逐步执行在 JBoss 中运行的代码。当我启动 JBoss 时,我使用以下选项:

set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MaxPermSize=256m -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n %JAVA_OPTS%

有没有办法加快执行速度?或者加快某些我不需要逐步执行的方法执行?


更新:似乎如果我不跳过/进入 CPU 密集型例程(即:只运行到在例程之后设置断点),那么执行时间就好像不在一个调试器。

【问题讨论】:

    标签: java debugging jboss intellij-idea


    【解决方案1】:

    提示:在 IDEA 中,您可以使用 ALT+F9 运行到您放置光标的位置,而不是设置额外的断点。

    有趣的是,如果您正在遍历可以从堆栈访问大量数据的代码,那么在 IDEA 中调试会变得非常缓慢。不要忘记,IDEA 会收集这些数据(当前在词法范围内的任何数据)并将其作为对象树呈现给您,以浏览您是否在“观看”,并在每个后续步骤(也许它每次都会重新创建树?)。

    当有一个大集合作为“当前”对象的实例变量时,这一点尤其明显。

    【讨论】:

      【解决方案2】:

      一些 CPU 密集型例程在通过调试器运行时会显着变慢。这是为什么呢?

      因为启用调试时,JITter 不会优化代码(通常,根本不会)。

      【讨论】:

      • 谢谢。你能详细说明一下这个优化过程吗?
      • 大多数虚拟机不读取字节码,执行等效指令,然后重复。这实在是太慢了。相反,他们所做的是将字节码作为一个整体,将其转换为等效的本机代码,然后执行本机代码。如果您在调试器下运行(因此说您可能会在某个时候跳过它),那么您对实际可以做的事情施加了一些相当大的限制。
      【解决方案3】:

      调试由 JIT 生成的优化代码将非常困难,因为一系列本机指令与一行 Java 代码之间没有直接关系,就像一系列 Java 字节码和一行之间存在关系一样Java 代码。

      因此,在调试器中闯入一个函数会迫使 JVM 取消优化您正在单步执行的方法。 Hotspot 根本不生成原生代码,只是解释方法的字节码。

      在 JDK 1.4.1 之前启用调试强制 JVM 仅使用解释器:http://java.sun.com/products/hotspot/docs/whitepaper/Java_Hotspot_v1.4.1/Java_HSpot_WP_v1.4.1_1002_3.html#full

      【讨论】:

        【解决方案4】:

        如果你使用Java 5,调试的参数是:

        -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=

        在 Java 5 之前

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

        【讨论】:

        • 不要因为您的第一篇文章被否决而生气。它只是没有回答问题。
        【解决方案5】:

        这也取决于“断点样式”。例如。在变量上设置观察点或在接口级别设置断点(调试器将在所有方法实现上停止)通常会显着减慢处理时间。

        【讨论】:

        • 非常感谢。我正在浪费大量时间,因为并且无法弄清楚为什么,我在一个在许多迭代中一直运行良好的进程上的远程调试会话开始一直运行缓慢。直到我读到这篇文章,我才想到它可能会受到我设置的断点的影响(不是断点命中,而是刚刚设置)。禁用我的所有断点并重新启用更有选择地对问题进行排序。
        • 看来断点的数量本身就是一个因素。我对启用/禁用进行了一些实验。在我当前的环境中,只要启用 >39 个断点,整个过程(从启动开始)就会变得非常缓慢。没关系。
        【解决方案6】:

        调试时,除了运行您的应用程序之外,您还运行了一个调试器。

        代码在调试模式下编译,带有关于局部变量和其他源级信息的元数据符号。调试器读取以了解哪一行源代码与当前指令相对应。该过程称为符号调试。存储的符号会增加代码大小,解释它们会增加执行时间。

        一些调试器实际上是即时解释代码,这几乎总是对性能造成重大影响。

        更多关于 Java 调试编译模式的信息,由javac 执行,在类文件中包含调试信息Java Language Compiler Options。 例如:-g 生成所有调试信息,包括局部变量。

        【讨论】:

        • +1 因为我从来没有遇到过这种情况(与数据库的连接速度很慢),这很可能
        • 当你说代码是在调试模式下编译时,你是指JVM把Java字节码编译成本机机器码?
        【解决方案7】:

        您确实需要考虑另一个程序 - 调试器 - 已挂钩到您的程序中,并且正在监视它是否存在异常等情况。它还监视当前行,以便对断点或用户请求的中断(如暂停请求或监视条件)做出反应。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多