Skip to content

Commit acbb4e6

Browse files
committed
Clear caches on ApplicationContext load
Ensure that JarFile caches are cleared once the ApplicationContext has loaded. Caches are cleared manually with the assumption that no further class loading is likely. Closes gh-4882
1 parent e2368b9 commit acbb4e6

File tree

5 files changed

+89
-0
lines changed

5 files changed

+89
-0
lines changed

spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java

+26
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
package org.springframework.boot.loader;
1818

1919
import java.io.IOException;
20+
import java.net.JarURLConnection;
2021
import java.net.URL;
2122
import java.net.URLClassLoader;
23+
import java.net.URLConnection;
2224
import java.security.AccessController;
2325
import java.security.PrivilegedExceptionAction;
2426
import java.util.Arrays;
@@ -228,6 +230,30 @@ public Object run() throws ClassNotFoundException {
228230
}
229231
}
230232

233+
/**
234+
* Clear URL caches.
235+
*/
236+
public void clearCache() {
237+
for (URL url : getURLs()) {
238+
try {
239+
URLConnection connection = url.openConnection();
240+
if (connection instanceof JarURLConnection) {
241+
clearCache(connection);
242+
}
243+
}
244+
catch (IOException ex) {
245+
}
246+
}
247+
248+
}
249+
250+
private void clearCache(URLConnection connection) throws IOException {
251+
Object jarFile = ((JarURLConnection) connection).getJarFile();
252+
if (jarFile instanceof JarFile) {
253+
((JarFile) jarFile).clearCache();
254+
}
255+
}
256+
231257
@UsesJava7
232258
private static LockProvider setupLockProvider() {
233259
try {

spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFile.java

+4
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,10 @@ private void setCertificates(JarEntry entry, java.util.jar.JarEntry certEntry) {
347347
}
348348
}
349349

350+
public void clearCache() {
351+
this.entries.clearCache();
352+
}
353+
350354
/**
351355
* Register a {@literal 'java.protocol.handler.pkgs'} property so that a
352356
* {@link URLStreamHandler} will be located to deal with jar URLs.

spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarFileEntries.java

+4
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,10 @@ private int getFirstIndex(int hashCode) {
270270
return index;
271271
}
272272

273+
public void clearCache() {
274+
this.entriesCache.clear();
275+
}
276+
273277
private AsciiBytes applyFilter(AsciiBytes name) {
274278
return (this.filter == null ? name : this.filter.apply(name));
275279
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2012-2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot;
18+
19+
import java.lang.reflect.Method;
20+
21+
import org.springframework.context.ApplicationListener;
22+
import org.springframework.context.event.ContextRefreshedEvent;
23+
import org.springframework.util.ReflectionUtils;
24+
25+
/**
26+
* {@link ApplicationListener} to cleanup caches once the context is loaded.
27+
*
28+
* @author Phillip Webb
29+
*/
30+
class ClearCachesApplicationListener
31+
implements ApplicationListener<ContextRefreshedEvent> {
32+
33+
@Override
34+
public void onApplicationEvent(ContextRefreshedEvent event) {
35+
ReflectionUtils.clearCache();
36+
clearClassLoaderCaches(Thread.currentThread().getContextClassLoader());
37+
}
38+
39+
private void clearClassLoaderCaches(ClassLoader classLoader) {
40+
if (classLoader == null) {
41+
return;
42+
}
43+
try {
44+
Method clearCacheMethod = classLoader.getClass()
45+
.getDeclaredMethod("clearCache");
46+
clearCacheMethod.invoke(classLoader);
47+
}
48+
catch (Exception ex) {
49+
// Ignore
50+
}
51+
clearClassLoaderCaches(classLoader.getParent());
52+
}
53+
54+
}

spring-boot/src/main/resources/META-INF/spring.factories

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer
1616

1717
# Application Listeners
1818
org.springframework.context.ApplicationListener=\
19+
org.springframework.boot.ClearCachesApplicationListener,\
1920
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
2021
org.springframework.boot.context.FileEncodingApplicationListener,\
2122
org.springframework.boot.context.config.AnsiOutputApplicationListener,\

0 commit comments

Comments
 (0)