尝试资源从根本上说是不安全的吗?

时间:2017-10-12 23:30:57

标签: java try-with-resources

我正在使用Java 7中引入的try-with-resources。该程序会下载多个HTTP资源并对其进行压缩。

import java.io.*;
import java.net.*;
import java.util.zip.GZIPOutputStream;

class Main {
    private static byte[] downloadAndCompress(URL url) throws IOException {
        ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
        HttpURLConnection connection = (HttpURLConnection)url.openConnection();
        try(
            Closeable closeConnection = () -> connection.disconnect();
            OutputStream gzipOutput = new GZIPOutputStream(byteOutput);
        ) {
            connection.connect();
            byte[] buffer = new byte[1024];
            int bytesRead;
            while (0 <= (bytesRead = connection.getInputStream().read(buffer))) {
                gzipOutput.write(buffer, 0, bytesRead);
            }
        }
        return byteOutput.toByteArray();

    }

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10; i++) {
            URL url = new URL("http://example.com?" + i);
            try {
                downloadAndCompress(url);
                // TODO: do something with result
            } catch (IOException e) {
                System.err.println("Failed to download " + url + ": " + e);
            }
        }
    }
}

我想知道如果(1)请求失败并且(2)写gzip预告片超过可用堆内存会发生什么。

所以我重新编写downloadAndCompare来测试:

        HttpURLConnection connection = (HttpURLConnection)url.openConnection();
        try(
            Closeable closeConnection = () -> connection.disconnect();
            OutputStream gzipOutput = new GZIPOutputStream(byteOutput) {
                public void close() { throw new OutOfMemoryError(); }
            };
        ) {
            throw new IOException("failed to download");
        }

运行它会产生

Failed to download http://example.com?0: java.io.IOException
Failed to download http://example.com?1: java.io.IOException
Failed to download http://example.com?2: java.io.IOException
Failed to download http://example.com?3: java.io.IOException
Failed to download http://example.com?4: java.io.IOException
Failed to download http://example.com?5: java.io.IOException
Failed to download http://example.com?6: java.io.IOException
Failed to download http://example.com?7: java.io.IOException
Failed to download http://example.com?8: java.io.IOException
Failed to download http://example.com?9: java.io.IOException

看来try-with-resources suppresses在关闭资源时遇到所有Throwables,无论是OutOfMemoryError,InterruptedException还是StackOverflowError。

我读到在OOM和其他错误发生后继续a very bad thing

这与这种语言结构如何协调?忽略OOM好吗? try-with-resource是否可以安全使用?

0 个答案:

没有答案