JDK ClassLoader.getResourceAsStream не работает? (нераскрытые ресурсы)

Я постараюсь доказать этоClassLoader.getResourceAsStream() открывает дваInputStreamsне закрывая ничего из этого и возвращая только один клиенту. Правильна ли моя логика? Источники JDK взяты из jdk1.8.0_25

Я попал в проблему нераскрытых ресурсов, используя Spring ClassPathResource в интервале (оригинальный вопрос), который используетClassLoader.getResourceAsStream получитьInputStream в файл свойств.

После расследования я обнаружил, чтоclassLoader.getResourceAsStream получаетURL отURL url = getResource(name); и тогда он открывает этот поток, ноURL url = getResource(name) уже открывает этот поток, JDK источникClassLoader:

    public InputStream getResourceAsStream(String name) {
        URL url = getResource(name); /* SILENTLY OPENS AND DON'T CLOSES STREAM */
        try {
            return url != null ? url.openStream() : null; /* SECOND OPEN !!! */
        } catch (IOException e) {
            return null;
        }
    }

Если мы будемclose() InputStream при условии, что мы закроем только поток, открытыйurl.openStream(), JDK источник:

    public final InputStream openStream() throws java.io.IOException {
        return openConnection().getInputStream();
    }

Я полагаю, чтопроблема в том, что JDK тихо открывает поток вURL url = getResource(name) только для получения объекта URL, который используется в дальнейшем для создания ** секунд (возвращается клиенту) поток **. Посмотрите на источники этого метода:

    public URL getResource(String name) {
        URL url;
        if (parent != null) {
            url = parent.getResource(name);
        } else {
            url = getBootstrapResource(name); <---- we end up calling that method
        }
        if (url == null) {
            url = findResource(name);
        }
        return url;
    }

И теперь, вgetBootstrapResource(name) момент, когда мы конвертируемResource вURL забыв об открытом потоке вResource!:

private static URL getBootstrapResource(String name) {
    URLClassPath ucp = getBootstrapClassPath();
    Resource res = ucp.getResource(name); <---- OPENING STREAM [see further]
    return res != null ? res.getURL() : null; <--- LOSING close() CAPABILITY
}

Зачемucp.getResource(name); такое открывающийся ресурс? Давайте посмотрим на этот метод:this.getResource(var1, true);который делегирует:

public Resource getResource(String var1, boolean var2) {
    if(DEBUG) {
        System.err.println("URLClassPath.getResource(\"" + var1 + "\")");
    }

    URLClassPath.Loader var3;
    for(int var4 = 0; (var3 = this.getLoader(var4)) != null; ++var4) {
        Resource var5 = var3.getResource(var1, var2); <-------- OPENING STREAM
        if(var5 != null) {
            return var5;
        }
    }

    return null;
}

ЗачемResource var5 = var3.getResource(var1, var2); это открытие потока? Смотри дальше:

Resource getResource(final String var1, boolean var2) {
        final URL var3;
        try {
            var3 = new URL(this.base, ParseUtil.encodePath(var1, false));
        } catch (MalformedURLException var7) {
            throw new IllegalArgumentException("name");
        }

        final URLConnection var4;
        try {
            if(var2) {
                URLClassPath.check(var3);
            }

            var4 = var3.openConnection(); <------------ OPENING STREAM
            InputStream var5 = var4.getInputStream();
            if(var4 instanceof JarURLConnection) {
                JarURLConnection var6 = (JarURLConnection)var4;
                this.jarfile = URLClassPath.JarLoader.checkJar(var6.getJarFile());
            }
        } catch (Exception var8) {
            return null;
        }

        return new Resource() {
            public String getName() {
                return var1;
            }

            public URL getURL() {
                return var3;
            }

            public URL getCodeSourceURL() {
                return Loader.this.base;
            }

            public InputStream getInputStream() throws IOException {
                return var4.getInputStream();
            }

            public int getContentLength() throws IOException {
                return var4.getContentLength();
            }
        };
    }

Мы можем увидетьopenConnection() а такжеgetInputStream(), которые не закрыты, и отступают через все звонки, возвращающиесяResource наконец, мы используем толькоgetURL() метод, завернутый вResource не закрывая этоInputStream только чтобы использовать этоURL возражать открыть самолет другойInputStream и вернуть его клиенту (какой клиент может закрыть coruse, но мы заканчиваем с первым закрытым потоком).

Так,не работает ClassLaoder.getResourceAsStream из-за утечки ресурсов?

Практическая сторона: я пользуюсьgetResourceAsStream вtry-with-resources блокировать, и все еще имеют нераскрытые проблемы с ресурсами при работе с именем файла, загружаемым таким образом каждые 30 секунд. Более того, все эти ресурсы закрыты на сборку мусора, что согласуется с потоком файловclose() вfinalize() метод.

Ответы на вопрос(1)

Ваш ответ на вопрос