28

我看到很多关于如何让 Intellij 打破异常的问题。我正在尝试做一些不同的事情:我想在断点处抛出一个异常,以便我可以看到如果在该代码处发生异常会发生什么。

我已经想出办法来强迫这一点。例如,如果我有一个名为 的变量willBeUsed,我可以打一个断点并添加一个显示 的手表willBeUsed = null这最终会触发 NullPointerException 。

但是我处于一种情况,我想抛出一个IOException看看会发生什么。没有办法欺骗我的代码这样做。当我添加一个throw new IOException()说它给我一个错误的手表时,“意外的令牌”。

作为一种解决方法,我可以修改代码以引发异常并重新部署。但我想知道是否有办法在调试器中执行此操作而无需修改源代码。

4

6 回答 6

35

您可以右键单击堆栈跟踪并选择“抛出异常”

在此处输入图像描述

(从 2018.1 版本开始。请参阅 JetBrains 问题:IDEA-148408

于 2017-10-24T13:33:19.263 回答
8

如何将throw语句放在一个if块中,只更改条件,例如:

boolean shouldThrowException = false;
// ....
if ( shouldThrowException ) //place breakpoint here
{
    throw new IOException();
}

当您遇到断点时,将 的值更改shouldThrowException为 true。

于 2013-06-13T18:28:37.900 回答
8

在“调试器”窗口的“框架”部分中,右键单击当前函数并选择“抛出异常”。然后输入要抛出的异常。

在此处输入图像描述

于 2018-10-05T12:39:19.163 回答
1

还有另一种方法可以利用 JVM HotSwapping。

假设您正在将代码部署到某个服务器。然后,当您启动应用程序时,请确保您打开远程调试(我认为您在调试并且正在谈论部署时已经打开了)。如果不是,那么它将在本地调试器中正常工作。

现在我有两个类,主要和其他。

package com.stackoverflow;

import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        doStuff();
    }

    private static void doStuff() throws IOException {
        System.out.println("doStuff");
        Other.otherStuff();
    }

    public static void throwException() throws IOException {
        throw new IOException();
    }
}


package com.stackoverflow;

import java.io.File;
import java.io.IOException;

public class Other {
    public static void otherStuff() throws IOException {
        File file = new File("Some_File.txt");
        file.createNewFile();
    }
}

throwException()只要它“全局”可用,就可以放置在任何地方,例如在某些 util 类中。为了方便起见,现在它只是放在我的 Main 类中。

现在我们可以在我们的doStuff()方法中设置一个断点,并且在保留在那里的同时,我们可以更改otherStuff()方法中的代码,以便它调用我们的静态throwException()方法。

public static void otherStuff() throws IOException {
    Main.throwException();
    File file = new File("Some_File.txt");
    file.createNewFile();
}

我们必须调用一些方法而不是调用throw new IOException(),否则我们会遇到错误Unreachable statement

然后我们可以按Ctrl++Shift重新F9编译Other类。现在它将是 HotSwapped(一个对话框将询问您是否真的要这样做)。

然后按继续,就会抛出异常。

然后可以将代码恢复到正常状态。

这样做的好处是重新编译的类甚至可以“通过网络”热交换到远程机器。

重要的是您重新编译的代码必须在另一个类中。您有断点的同一类将无法正确重新加载。

作为一种解决方法,我可以修改代码以引发异常并重新部署。但我想知道是否有办法在调试器中执行此操作而无需修改源代码。

您将在调试器中修改代码,但仅在您需要的时候进行。然后,您可以恢复小更改并重新编译以热交换回旧代码。

我希望你明白这个想法(不是双关语)。

如果你愿意,我可以添加截图。

于 2013-06-13T21:52:34.807 回答
1

我看不出这是怎么做到的。我尝试了两种方法(也许我的想法会引出其他一些想法

1)我尝试使用调试器“记录评估表达式”,throw new IOException()但我得到的只是一条消息,IDEA 无法评估表达式。

2)我还尝试设置一个断点,当它停止时,我打开“评估表达式”对话框以抛出一个新异常,但这也不起作用。

我不认为调试器可以抛出异常。@Binyamin 的解决方案将起作用,但您已经在问题中提到了这一点。我只能在 IDEA 中添加,可以取消选中“暂停”复选框并输入shouldThrowException = true“日志评估表达式”框中。这将导致调试器仅更改值(并记录它)但不会停止,这在具有许多并发线程的代码中非常有用。

于 2013-06-13T18:43:30.843 回答
1

我不知道您是否尝试过,但您也许可以创建一个仅抛出的静态方法,IOException然后通过发出Evaluate Expression.

简单示例代码:

package com.stackoverflow;

import java.io.IOException;

public class Main {
    public static void main(String[] args) {

        doStuff();
    }

    private static void throwException() throws IOException {
        throw new IOException();
    }

    private static void doStuff() {
        System.out.println("doStuff");
    }
}

在行上设置断点System.out.println

在此处输入图像描述

调出Evaluate Expression...窗口并调用throwException方法(评估),然后您将从内部获得堆栈跟踪doStuff

在此处输入图像描述

当然会出现异常,throwException但您也会看到整个调用堆栈。

于 2013-06-13T20:20:04.447 回答