По какой причине setDefaultUseCaches (false) URLConnection охотно вызывается в org.apache.catalina.core.JreMemoryLeakPreventionListener - PullRequest
1 голос
/ 16 августа 2011

Этот вопрос может быть немного трудно найти ответ. Это вопросы из одной серии с По какой причине рассматривается Policy.getPolicy (), поскольку он сохраняет статическую ссылку на контекст и может вызвать утечку памяти . Вы можете прочитать его, чтобы узнать больше информации.

Исходный код извлекается из org.apache.cxf.common.logging.JDKBugHacks, а также из org.apache.catalina.core.JreMemoryLeakPreventionListener.

Есть кусок кода. Вот оно.

URL url = new URL("jar:file://dummy.jar!/"); 
URLConnection uConn = new URLConnection(url) {

    @Override
    public void connect() throws IOException{ 
        // NOOP
    }

};
uConn.setDefaultUseCaches(false);

В комментарии сказано:

/*
 * Several components end up opening JarURLConnections without
 * first disabling caching. This effectively locks the file.
 * Whilst more noticeable and harder to ignore on Windows, it
 * affects all operating systems.
 * 
 * Those libraries/components known to trigger this issue
 * include:
 * - log4j versions 1.2.15 and earlier
 * - javax.xml.bind.JAXBContext.newInstance()
 */

Однако я с трудом могу это понять. Почему они охотно звонили setDefaultUseCaches(false) и почему в Windows вредно, что по умолчанию кеш имеет значение true? Я не могу найти подсказку в java.net.JarURLConnection.

1 Ответ

4 голосов
/ 16 августа 2011

Я сам найду ответ. Любой может исправить меня, если вы думаете, что я неправ. в sun.net.www.protocol.jar.JarURLConnection. Я предполагаю, что это реализация по умолчанию java.net.JarURLConnection. Ниже приведен фрагмент кода.

Если для кеша установлено значение true, то соединение JarFile не будет закрыто. Что означает, что он заблокирован.

class JarURLInputStream extends java.io.FilterInputStream {
        JarURLInputStream (InputStream src) {
            super (src);
        }
        public void close () throws IOException {
            try {
                super.close();
            } finally {
                if (!getUseCaches()) {
                    jarFile.close(); //will not close
                }
            }
        }
    }



    public void connect() throws IOException {
        if (!connected) {
            /* the factory call will do the security checks */
            jarFile = factory.get(getJarFileURL(), getUseCaches());

            /* we also ask the factory the permission that was required
             * to get the jarFile, and set it as our permission.
             */
            if (getUseCaches()) {
                jarFileURLConnection = factory.getConnection(jarFile);
            }

            if ((entryName != null)) {
                jarEntry = (JarEntry)jarFile.getEntry(entryName);
                if (jarEntry == null) {
                    try {
                        if (!getUseCaches()) {
                            jarFile.close();  //will not close
                        }
                    } catch (Exception e) {
                    }
                    throw new FileNotFoundException("JAR entry " + entryName +
                                                    " not found in " +
                                                    jarFile.getName());
                }
            }
            connected = true;
        }
    }
...