为了账号安全,请及时绑定邮箱和手机立即绑定

Java:错误处理能力差,最后扔进去

Java:错误处理能力差,最后扔进去

慕妹3146593 2023-06-21 13:34:28
我有以下代码正在通过 fortify 运行。为什么它被标记为糟糕的错误处理,最后扔进去?private String getResourceContent(String fileName) throws IOException {    try (InputStream resource = ErrorResource.classLoader.getResourceAsStream(fileName)) {        return new String(resource.readAllBytes(), StandardCharsets.UTF_8);    } catch (NullPointerException n) {        throw new ErrorDescriptorException(                String.format("Error loading Error description data from Resource file [%s].", fileName), n);    }}
查看完整描述

3 回答

?
HUX布斯

TA贡献1876条经验 获得超6个赞

解释

让我快速引用重要部分:

throw在块内使用语句finally会破坏 try-catch-finally 的逻辑进程。

在 Java 中,finally 块始终在相应的 try-catch 块之后执行,并且通常用于释放分配的资源,例如文件句柄或数据库游标。在 finally 块中抛出异常可以绕过关键的清理代码,因为正常的程序执行将被中断

因此,您可以通过这样做轻松绕过清理代码,从而导致资源泄漏。

虽然在代码中不直接可见,但实际上有一个隐藏 finally块,因为您使用的是try-with-resources,它会自动关闭 finally 块中的资源。


例子

这是官方文档中的示例:

public void processTransaction(Connection conn) throws FileNotFoundException {

    FileInputStream fis = null;

    Statement stmt = null;

    try {

        stmt = conn.createStatement();

        fis = new FileInputStream("badFile.txt");

        ...

    } catch (FileNotFoundException fe) {

        log("File not found.");

    } catch (SQLException se) {

        // handle error

    } finally {

        if (fis == null) {

            // This bypasses cleanup code

            throw new FileNotFoundException();

        }


        if (stmt != null) {

            try {

                // Not executed if the exception is thrown

                stmt.close();

            }

            catch (SQLException e) {

                log(e);

            }

        }

    }

}

抛出时绕过stmt.close()对的调用。FileNotFoundException


笔记

为什么要检查是否null使用 aNullPointerException而不是基本的if-else?很少有正当理由去抓捕NullPointerException。做就是了:

try (InputStream resource = ErrorResource.classLoader.getResourceAsStream(fileName)) {

    if (resource == null) {

        // TODO Throw your exception here

    }

    return new String(resource.readAllBytes(), StandardCharsets.UTF_8);

}

通过告知无法找到资源的确切原因,它也可能有助于改进错误消息。



查看完整回答
反对 回复 2023-06-21
?
守着一只汪

TA贡献1872条经验 获得超3个赞

考虑以下代码,它大致基于您的代码:


String throwing(InputStream inputStream) throws IOException {

    try (InputStream resource = inputStream) {

        return "good";

    } catch (NullPointerException n) {

        return "bad";

    }

}

你看,这里没有抛出异常。尽管如此,你还是无法移除这个throws IOException部分——那是怎么回事?好吧,InputStream#close()可以抛出它,它将位于finallytry-with-resources 语句创建的隐式块中。我想您对此无能为力,它看起来像是 Fortify 误报。


查看完整回答
反对 回复 2023-06-21
?
MMMHUHU

TA贡献1834条经验 获得超8个赞

除了工具中的误导性消息之外,您的代码中实际上存在糟糕的错误处理,原因有多种:

  • 捕捉 NPE 是非常糟糕的做法。要么它是一个错误(某些东西是 null 并且不应该),要么你的代码缺少检查if (whatever == null)和相应的代码来处理这种预期情况

  • 假设这个 NPE 具有您在新 Exception 中表达的确切含义,只是猜测

换句话说:在没有更多信息的情况下,不清楚您的工具到底抱怨什么。但是:不需要工具来理解:这是糟糕的错误处理。

除此之外,此类工具通常会提供有关其警告的某种信息。意思是:该警告可能带有一个“错误 ID”,您应该能够在您的工具文档中查找该“错误 ID”以获得进一步的解释。


查看完整回答
反对 回复 2023-06-21
  • 3 回答
  • 0 关注
  • 119 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信