Description
The AbstractFileResolvingResource
in Spring 5.3.39 has a resource leak (seems to still be present at least in 6.2.2).
The leak occurs when the exists()
method is called on a UrlResource
obtained from a JAR/ZIP file which is not on the classpath.
exists()
will open a connection and may then call a variation of getContentLengthLong()
on it to obtain the size of the resource to check if it exists by comparing the size to 0.
Leak: Calling getContentLengthLong()
on a JarURLConnection
opens the underlying JAR file. However, that file is then not closed anymore.
The problem can be checked e.g. by using https://github.com/jenkinsci/lib-file-leak-detector
Here a stack using Spring 5.3.39
#8 /var/folders/mr/5jj8y27x76s6zd22d78gqcfw0000gn/T/junit-4912917014845844348/zip/hash-in-file.zip by thread:ForkJoinPool-1-worker-1 on Mon Mar 03 11:41:06 CET 2025
at java.base/java.io.RandomAccessFile.<init>(RandomAccessFile.java:214)
at java.base/java.util.zip.ZipFile$Source.<init>(ZipFile.java:1312)
at java.base/java.util.zip.ZipFile$Source.get(ZipFile.java:1277)
at java.base/java.util.zip.ZipFile$CleanableResource.<init>(ZipFile.java:709)
at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:243)
at java.base/java.util.zip.ZipFile.<init>(ZipFile.java:172)
at java.base/java.util.jar.JarFile.<init>(JarFile.java:347)
at java.base/sun.net.www.protocol.jar.URLJarFile.<init>(URLJarFile.java:103)
at java.base/sun.net.www.protocol.jar.URLJarFile.getJarFile(URLJarFile.java:72)
at java.base/sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:168)
at java.base/sun.net.www.protocol.jar.JarFileFactory.getOrCreate(JarFileFactory.java:91)
at java.base/sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:132)
at java.base/sun.net.www.protocol.jar.JarURLConnection.getContentLengthLong(JarURLConnection.java:202)
at org.springframework.core.io.AbstractFileResolvingResource.exists(AbstractFileResolvingResource.java:69)
The issue e.g. prevents temporary folders from unit tests containing ZIP resources accessed through Spring to be deleted on Windows.