0

在Java 中,检查异常和未检查异常都可以显式抛出,即通过throw语句。此外,未经检查的异常ArithmeticExceptionOutOfMemoryError可以在没有任何明确throw声明的情况下触发,如下所示:

public static void throwArithmeticException() {
    int i = 1;
    int j = i / 0;
}

public static void throwOutOfMemoryError() {
    List<Object> list = new ArrayList<>();
    while(true) {
        list.add(new Object());
    }
}

所以我的问题是,有什么方法可以触发一个已检查的异常,比如IOException隐式地,即不使用任何throw语句?

4

2 回答 2

5

你可以做到,但你不应该1

我假设您正在谈论athrow字节码指令。(而且您真的问是否可以在不使用语句的情况下从代码中触发异常。)throw

应用程序有(至少)两种方法可以抛出不涉及显式athrow指令的任意 Java 异常(已检查或未检查)。

  1. 你可以打电话Unsafe.throwException(Throwable)

  2. 在本机代码中,您可以调用 JNI API 中的ThrowThrowNew函数。

在这两种情况下,您都可以规避 Java(编译时和验证程序)检查,这些检查旨在确保始终声明(通过throws子句)或处理检查的异常。

注意使用Unsafe或本机代码意味着您的代码不是纯 Java。它不会是便携式的。此外,很容易做一些会使 JVM 不稳定的事情。JVM 崩溃并不罕见。


此外,JVM 本身会在没有athrow指令的情况下抛出异常。例如,如果您尝试使用new FileInputStream打开一个不存在并被FileNotFoundException抛出的文件,那么它是从本机代码中抛出的,而不是从编译的 Java 代码中抛出的。

因此,您的应用程序可以使用此机制隐式抛出许多已检查和未检查的异常;例如,故意试图打开一个不存在的文件。但是,方法签名read声明它可能会抛出IOException,所以编译器知道这一点......从检查异常规则的角度来看。


1 - 如果你的应用程序设计需要这种疯狂,你会被建议想出一个替代方案。尝试与 Java 的检查异常规则作斗争是个坏主意。如果您非常不喜欢它们以至于您正在考虑这样做,那么您应该选择一种不同的编程语言。

于 2021-05-09T08:53:13.350 回答
1

在 java 字节码中,这仅适用于 JVM 可以自己生成的异常,但IOException不是其中之一。您只能使用虚拟机抛出由解释字节码抛出的运行时异常。例如这段代码:

aconst_null
monitorexit

会抛出一个NullPointerException. 理论上,这对于像 NegativeArraySizeException, IllegalMonitorStateException, WrongMethodTypeException,和许多其他的投掷物也是可能的。你可以在这里找到更多BootstrapMethodErrorIncompatibleClassChangeError

于 2021-05-09T09:09:13.097 回答