微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

是否可以在没有任何 athrow 指令的情况下隐式抛出已检查的异常?

如何解决是否可以在没有任何 athrow 指令的情况下隐式抛出已检查的异常?

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

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 语句?

解决方法

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

我假设您在谈论 athrow bytecode instruction。 (并且您真的询问是否可以在不使用 throw 语句的情况下从代码中触发异常。)

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

  1. 您可以拨打Unsafe.throwException(Throwable)

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

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

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


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

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


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

,

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

aconst_null
monitorexit

会抛出一个 NullPointerException。这理论上也适用于 NegativeArraySizeExceptionIllegalMonitorStateExceptionWrongMethodTypeExceptionBootstrapMethodErrorIncompatibleClassChangeError 和许多其他可抛出对象。您可以了解更多here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。