更新:虽然我在一年前提出这个问题,但仍然没有答案。出于好奇,我用IntelliJ IDEA重现了我今天用Eclipse观察到的问题。
我最近调试了一个包含阻塞和长时间运行方法的类,它执行大量操作。有趣的是,调试速度不时变化非常。我感觉速度与不同的调试方法相关(Step Into,Step Over,Step Return,Resume)。
我写了一个最小的例子,可以在下面的课程的帮助下重现和衡量我的感受:
测试类只测量计数器在长时间运行中增加的频率"操作。为了测试这个假设,我在调用longRunningOperation
之前设置了一个断点来暂停程序,然后应用了不同的调试方法。
鉴于显示断点,我使用不同的调试策略以无特定顺序(以最小化系统错误的可能性)执行多次重复测量:
| # | Run | W/O Breakpoint | Resume | Over | Into+Return | Into+Resume | |-----------|-----------|----------------|-----------|----------|-------------|-------------| | 1 | 863342711 | 862587196 | 872204399 | 14722473 | 12550871 | 870687830 | | 2 | 868929379 | 864245840 | 872166407 | 14139145 | 12487883 | 870626416 | | 3 | 865544040 | 852645848 | 872988659 | 14352193 | 12459235 | 871062770 | | 4 | 868100763 | 863198685 | 867518560 | 12261625 | 14696307 | 871365658 | | 5 | 865157647 | 866257267 | 862671156 | 12524087 | 14620150 | 868541690 | | 6 | 865348827 | 863449576 | 864416490 | 14410005 | 14592026 | 868784314 | | 7 | 866957323 | 865379147 | 873324542 | 14326951 | 12648924 | 868621635 | | 8 | 860129057 | 868993541 | 867785706 | 14434965 | 14380032 | 875011465 | | 9 | 865961737 | 857872085 | 871137322 | 12440011 | 12262172 | 871357411 | | 10 | 865517465 | 864911063 | 865109071 | 14544906 | 12391397 | 871574154 | | | | | | | | | | Mean | 865498895 | 862954025 | 868932231 | 13815636 | 13308900 | 870763334 | | Deviation | 0,00% | 0,29% | -0,40% | 98,40% | 98,46% | -0,61% |
每个调试策略执行了10次,System.out.println(res)
的结果显示在各自的列中。 Mean
行包含每个策略的10个度量值的平均值。 Deviation
行包含与运行策略的相对偏差。结果是使用IntelliJ IDEA获得的,但在Eclipse中类似。
结果表明,在调试过程中使用步骤或步进+步出执行长时间运行的方法超过 10x慢与其他选项相比。但是我无法解释为什么会发生这种情况?调试器内部做了什么来产生这种行为?
注意:我使用Java 8和IntelliJ IDEA 2016.2在Windows 10上执行了测量。
要重现您机器上的行为,我已将小班放入Gist。
答案 0 :(得分:1)
我也观察到了这一点。在eclipse中必须是一个糟糕的跨越实现。我通常在复杂方法之后设置断点,然后使用恢复跳转,而不是使用跳过,因为恢复通常更快。
由于跳过可以在内部进行编程,就像设置断点并按恢复一样,这可能只是以不好的方式实现。
编辑:刚刚意识到它不一样。当您按下resume并跳转到断点时,您可能会停在由其他线程触发的断点处。
答案 1 :(得分:1)
我仍然遇到相同的问题,我认为它的实现方式不像一般的Java调试(如果是实现方式的错误,IntelliJ必须同样严重地实现它,并且两个IDE都很难实现它,这似乎不太可能给我)。
我在SO上发现this post,这使我怀疑,单步执行代码时,Java不会一步步离开未优化的解释字节码。我相信当继续时,它会检查它可以运行到哪一点,并以优化的方法进行检查,从而使处理速度更快。
但是请注意,这只是我个人的怀疑,我没有任何事实可以证明这一点(这些操作的执行情况除外)。
但是,我确实找到了解决此问题的“方法”。即:Run to Line
。
此功能将代码运行到光标当前所在的行。因此,它似乎与向该行添加断点,继续执行并再次删除该断点具有相同的效果。通过这种方法,可以通过将光标放在下一行并点击Ctrl+R
(此操作的默认快捷键)来“跳过”一行。