Java:糟糕的错误处理,Throw inside Finally

标签 java 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);
    }
}

最佳答案

解释

这在官方文档中有很好的解释(参见 Poor Error Handling: Throw Inside Finally )。让我快速引用重要部分:

Using a throw statement inside a finally block breaks the logical progression through the try-catch-finally.

In Java, finally blocks are always executed after their corresponding try-catch blocks and are often used to free allocated resources, such as file handles or database cursors. Throwing an exception in a finally block can bypass critical cleanup code since normal program execution will be disrupted.

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

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

另见 Throwing an exception inside 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);
            }
        }
    }
}

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


注意事项

为什么要使用 NullPointerException 而不是基本的 if-else 检查 null?很少有有效的理由来捕获 NullPointerException。只是做:

try (InputStream resource = ErrorResource.classLoader.getResourceAsStream(fileName)) {
    if (resource == null) {
        // TODO Throw your exception here
    }
    return new String(resource.readAllBytes(), StandardCharsets.UTF_8);
}

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

关于Java:糟糕的错误处理,Throw inside Finally,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57673658/

相关文章:

c# - 在 .dll 文件和 .cs 上运行 Fortify

security - 强化 SSC "attack surface"选项

java - URLEncoder.encode(string, "UTF-8") 是一个糟糕的验证吗?

Java-使用InputStream作为文件

command - 如何使用命令行将审核的 fpr 文件与新扫描的 fpr 文件合并?

java - 如何使用 android studio 更改 Google map 中“我的位置”按钮的位置

java - Android Studio Webview 1101 Activity

java - 保护静态 SQL 查询免遭 SQL 注入(inject)

java - 是否可以使用代号一将 eclipse 中的 android 应用程序转换为 ios Rim 窗口?

java - JodaTime:plusMonths(1) 两次不同于 plusMonths(2)