在org.apache.catalina.core.JreMemoryLeakPreventionListener中急切调用URLConnection的setDefaultUseCaches(false)的原因是什么

这个问题可能有点难以找到答案。 这是一个系列中的问题。 考虑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上,默认缓存是真的有害? 我在java.net.JarURLConnection找不到任何线索。

我自己找到答案。 如果你认为我错了,任何人都可以纠正我。 在sun.net.www.protocol.jar.JarURLConnection 。 我假设这是java.net.JarURLConnection的默认实现。 下面有一段代码。

如果cache设置为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; } }