什么时候会抛出 IOError?

31

我从未见过抛出 IOError 的情况。文档中对于 IOError 只有这样一句话:

当发生严重的 I/O 错误时抛出。

没有任何子类或其他明显的东西。

在 Java 中是否存在 IOError 被抛出的情况?可能会导致它的原因是什么?

(这与 IOException 不要混淆——IOException 在很多情况下都会被抛出,并且经常被使用;我知道这一点。 我想知道的是不太常见的 IOError)。


2
@Harvtronix 这个问题是关于 IOError,而不是 IOException - takendarkk
@Harvtronix 是的,我最初链接到了IOException。但是我指的是IOError。似乎人们混淆了这两个?我可能需要编辑一下以使其更清晰(编辑:我已经进行了编辑来解决这个问题)。 - Pokechu22
糟糕!我的错。对不起! - Harvtronix
1
我觉得问题很清晰明了,但是已经发布的三个答案(其中一个已删除)似乎都误解了问题。 - Wyzard
8个回答

18

ConsolePath#toAbsolutePathPath#toUri声明可能抛出此特定异常。当然,这是文档说明而不是实际声明;因为Error是运行时异常,在签名中声明将没有意义。

从代码上看,Console#readLineConsole#readPassword捕获由其正常操作引起的IOException,然后将其传播到IOError中。

本质上,IOError表示底层文件系统的严重故障,或访问将Java与文件系统绑定的某些资源。它不经常抛出,但如果文件系统内部发生了严重情况,则有可能抛出。


@PhilippWendler:我使用的是Linux系统,所以它们对我来说不会抛出异常。我只是大致涵盖了触发该异常的一般情况。 - Makoto
1
由于Error是一个运行时异常,这是一个不正确的说法。RuntimeExceptionException的子类型。ErrorThrowable的另一类别。 - hfontanez
@hfontanez - 我确实说过这是一个"运行时异常",意思是在运行时可能会出现异常,而不是它是RuntimeException的子类,这两个概念完全不同。这两种异常都会在运行时被抛出。只有RuntimeException或其子类才有意义被应用程序捕获或处理。 - Makoto
同时,@hfontanez只有需要声明抛出的Exception。因此,其他所有内容都不需要声明。也就是说,每个实际运行时异常都不需要声明抛出,因为在应用程序运行期间无法处理IOError - Makoto
@Makoto你写道[I did say it was a "runtime exception"]。再次强调,该声明是不正确的。请阅读Java异常文档,ErrorExceptions并不相同,不应以相同方式处理。这不是我的话。这是Java语言架构师的话。请阅读我发布的答案。 - hfontanez

6
在Java中,是否会出现IOError抛出的情况?
import java.io.IOError;

public class Test {

    public static void main(String[] args) {
        throw new IOError(new Exception());
    }

}

会导致
Exception in thread "main" java.io.IOError: java.lang.Exception
    at test.Test.main(Test.java:13)
Caused by: java.lang.Exception
    ... 1 more
Java Result: 1

我相信您希望看到更有可能发生的情况。

例如,当尝试从输入流已关闭的控制台读取时,将抛出IOError

您可以尝试运行此代码片段:

import java.io.*;

public class Test {

    public static void main(String[] s) {
        Console con = System.console();
        try {
            InputStreamReader reader = new InputStreamReader(System.in);
            reader.close();
            String st = con.readLine("%s", "Enter a line");
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IOError error) {
            error.printStackTrace();
        }
    }
}

这将导致

java.io.IOError: java.io.IOException: Stream Closed
    at java.io.Console.readLine(Console.java:254)
    at Test.main(Test.java:10)
Caused by: java.io.IOException: Stream Closed
    at java.io.FileInputStream.readBytes(Native Method)
    at java.io.FileInputStream.read(FileInputStream.java:246)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    at java.io.Console$LineReader.read(Console.java:437)
    at java.io.Console.readline(Console.java:376)
    at java.io.Console.readLine(Console.java:250)
    ... 1 more

6

以下是来自Oracle的Mark Reinhold的解释:

新的IOError类与新的java.io.Console类一起定义。它用于在发生不可恢复的I/O错误并且最合适的响应是终止程序而不是尝试处理异常的情况下使用。

IOError类以及许多其他增强功能将在JCP中即将发布的Mustang维护审查中得到记录。

http://cafe.elharo.com/blogroll/undocumented-changes-in-java-6-mustang-ioerror/


4

IOError很少使用。我认为它的主要用法是在java.io.Console#readLine()readPassword()中,这两个方法默认情况下不会抛出IOExeption(但包装它),以便向用户发出I / O问题的信号。

我猜测这样做的动机是因为它很少发生,他们不想声明一个受检异常。当终端出现问题时,可能会发生这种情况-现在只有在严重的系统条件下才会发生,例如内存耗尽或句柄用完。


4
寻找官方来源之一是Java Bug Database,在此可使用搜索关键字查找涉及IOError的错误。这可以展示一些实际涉及此错误的案例。
至少我所能找到的一个直接涉及此错误的案例发生在JDK-6347312中,该问题与Console.readLine()有关。
在JDK中也很少使用。最可能用于信号"关键"IOException型异常,而调用者不应处理此类异常(与其他运行时异常类似)。

1
一个奇怪的回答。如果没有与 IOError 相关的错误,那怎么办?这真的证明它从未被使用过吗? - user207421
2
@EJP 我的意图是展示出发生 IOError 的真实情况,而不是关于它的错误。我已经删除了关于它很少使用的结论部分。 - M A

3

IOError 是一种运行时异常,属于未经检查的异常错误类别。在我看来,它通常会在使用JNI/本地调用与JVM交互,并通过底层操作系统调用访问IO设备(存储、键盘、显示器、网络等)时出现。但是在Java API文档中很少见到其使用。最可能的原因是实现者希望将对底层系统的依赖降至最低。


2

补充一下,RedHat JBoss Wildfly域管理库在其ConsoleWrapper接口中明确抛出IOError。 迄今为止,我所见过的该接口的唯一实现是JavaConsole类。

来源:

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2012, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jboss.as.domain.management.security.adduser;

import java.io.IOError;
import java.util.IllegalFormatException;

/**
 * Wrap the console commands
 *
 * @author <a href="mailto:flemming.harms@gmail.com">Flemming Harms</a>
 */
public interface ConsoleWrapper<T> {

    /**
     * Writes a formatted string to this console's output stream using
     * the specified format string and arguments.
     * see <a href="../util/Formatter.html#syntax">Format string syntax</a>
     * @param fmt
     * @param args
     */
    T format(String fmt, Object ...args) throws IllegalFormatException;

    /**
     * A convenience method to write a formatted string to this console's
     * output stream using the specified format string and arguments.
     *
     * @param format
     * @param args
     * @throws IllegalStateException
     */
    void printf(String format, Object ... args) throws IllegalFormatException;

    /**
     * Provides a formatted prompt, then reads a single line of text from the
     * console.
     *
     * @param fmt
     * @param args
     * @return A string containing the line read from the console, not
     *          including any line-termination characters, or <tt>null</tt>
     *          if an end of stream has been reached.
     * @throws IOError
     */
    String readLine(String fmt, Object ... args) throws IOError;

    /**
     * Provides a formatted prompt, then reads a password or passphrase from
     * the console with echoing disabled.
     *
     * @param fmt
     * @param args
     * @return  A character array containing the password or passphrase read
     *          from the console.
     * @throws IOError
     */
    char[] readPassword(String fmt, Object ... args) throws IllegalFormatException, IOError;

    /**
     *  Return the console object
     *
     * @return Return the console object
     */
    T getConsole();
}

-1

我不确定为什么有这么多人声称错误是运行时异常。它们并不是。只需查看API即可。 Error 是一个与 Exception 不同的 Throwable 类别。 RuntimeExceptionException 的子类型。

简单来说,Error(及其子类型)用于指示严重问题,一个合理的应用程序不应该尝试捕获。另一方面,Exception 用于指示条件,一个合理的应用程序可能想要捕获。它并没有说你必须。之所以说可能是因为 RuntimeExceptionException 的子类型,任何导致运行时异常的情况都应该在开发期间进行修复(最有可能),以便在部署应用程序时,不需要处理这些类型的条件。但是,继续使用 catch 子句的选项是开放的。

底线: Error 不是 RuntimeException。这样说是完全错误的。


看起来Java将ErrorRuntimeException的子类称为“未检查异常”:https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/lang/Error.html,https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/lang/RuntimeException.html。然而,这应该是对答案的评论,而不是答案本身。 - Solomon Ucko
@SolomonUcko并不是那个被授予50赏金点并获得5次赞的人。 - hfontanez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接