【问题标题】:Is it possible to throw an checked Exception implicitly, without any athrow instruction?是否可以在没有任何抛出指令的情况下隐式抛出已检查的异常?
【发布时间】:2021-05-09 08:40:21
【问题描述】:

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

【问题讨论】:

  • 这纯粹是出于兴趣/乐趣,还是您有更大的目标?
  • java 语言中没有“athrow”指令(甚至不是keyword)。此外,所有Throwables 都必须是thrown 才能产生异常效果。否则,它们只是普通对象。 ---对我来说,这个问题还不清楚。请edit发帖并澄清问题。
  • @Sweeper 我的研究课题是异常相关的,所以对异常处理的机制很感兴趣。
  • 感谢@Turing85 的建议,我已经编辑并澄清了问题。
  • 您的意思是“在任何地方都没有throw 吗?例如,Thread.currentThread().interrupt(); Thread.sleep(1); 会导致抛出检查异常,但在某处抛出了一些东西。

标签: java exception checked-exceptions unchecked-exception


【解决方案1】:

你可以这样做,但你不应该1

我假设您说的是athrow bytecode instruction。 (而且您真的询问是否可以在不使用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 的检查异常规则作斗争是个坏主意。如果你非常不喜欢它们以至于你正在考虑这样做,你应该选择一种不同的编程语言。

【讨论】:

  • 为什么使用Unsafe 会使您的代码不是纯Java?您的意思是说它不是“标准”Java API,而是特定于 JDK 实现的东西?
  • 是的。 Unsafe 在其 API 中是特定于实现的。最重要的是,“安全地”使用Unsafe 有各种特定的实现方面......如果你明白我的意思的话。
  • @StephenC 感谢您的详尽回答!
【解决方案2】:

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

aconst_null
monitorexit

将抛出一个NullPointerException。理论上,这对于像 NegativeArraySizeExceptionIllegalMonitorStateExceptionWrongMethodTypeExceptionBootstrapMethodErrorIncompatibleClassChangeError 和许多其他的投掷物也是可能的。你可以了解更多here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-21
    • 2021-06-07
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多