Skip to content

Commit ecfc8d7

Browse files
committed
Be defensive when clearing caches for restart
Update `Restarter` to be much more defensive when attempting to clear caches. We now use `clearCache()` methods whenever possible, and only fall back to field access when absolutely necessary. In addition field access now ignore any exceptions. Fixes gh-12719
1 parent 4e0afaf commit ecfc8d7

File tree

1 file changed

+59
-22
lines changed
  • spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart

1 file changed

+59
-22
lines changed

spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/Restarter.java

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2016 the original author or authors.
2+
* Copyright 2012-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -341,16 +341,47 @@ private void cleanupCaches() throws Exception {
341341
private void cleanupKnownCaches() throws Exception {
342342
// Whilst not strictly necessary it helps to cleanup soft reference caches
343343
// early rather than waiting for memory limits to be reached
344-
clear(ResolvableType.class, "cache");
345-
clear("org.springframework.core.SerializableTypeWrapper", "cache");
344+
clearResolvableTypeCache();
345+
clearCachedIntrospectionResultsCache();
346+
clearReflectionUtilsCache();
347+
clearAnnotationUtilsCache();
348+
clear("com.sun.naming.internal.ResourceManager", "propertiesCache");
349+
}
350+
351+
private void clearResolvableTypeCache() throws Exception {
352+
try {
353+
ResolvableType.clearCache();
354+
}
355+
catch (Throwable ex) {
356+
clear(ResolvableType.class, "cache");
357+
clear("org.springframework.core.SerializableTypeWrapper", "cache");
358+
}
359+
}
360+
361+
private void clearCachedIntrospectionResultsCache() throws Exception {
346362
clear(CachedIntrospectionResults.class, "acceptedClassLoaders");
347363
clear(CachedIntrospectionResults.class, "strongClassCache");
348364
clear(CachedIntrospectionResults.class, "softClassCache");
349-
clear(ReflectionUtils.class, "declaredFieldsCache");
350-
clear(ReflectionUtils.class, "declaredMethodsCache");
351-
clear(AnnotationUtils.class, "findAnnotationCache");
352-
clear(AnnotationUtils.class, "annotatedInterfaceCache");
353-
clear("com.sun.naming.internal.ResourceManager", "propertiesCache");
365+
}
366+
367+
private void clearReflectionUtilsCache() throws Exception {
368+
try {
369+
ReflectionUtils.clearCache();
370+
}
371+
catch (Throwable ex) {
372+
clear(ReflectionUtils.class, "declaredFieldsCache");
373+
clear(ReflectionUtils.class, "declaredMethodsCache");
374+
}
375+
}
376+
377+
private void clearAnnotationUtilsCache() throws Exception {
378+
try {
379+
AnnotationUtils.clearCache();
380+
}
381+
catch (Throwable ex) {
382+
clear(AnnotationUtils.class, "findAnnotationCache");
383+
clear(AnnotationUtils.class, "annotatedInterfaceCache");
384+
}
354385
}
355386

356387
private void clear(String className, String fieldName) {
@@ -363,23 +394,29 @@ private void clear(String className, String fieldName) {
363394
}
364395

365396
private void clear(Class<?> type, String fieldName) throws Exception {
366-
Field field = type.getDeclaredField(fieldName);
367-
field.setAccessible(true);
368-
Object instance = field.get(null);
369-
if (instance instanceof Set) {
370-
((Set<?>) instance).clear();
371-
}
372-
if (instance instanceof Map) {
373-
Map<?, ?> map = ((Map<?, ?>) instance);
374-
for (Iterator<?> iterator = map.keySet().iterator(); iterator.hasNext();) {
375-
Object value = iterator.next();
376-
if (value instanceof Class && ((Class<?>) value)
377-
.getClassLoader() instanceof RestartClassLoader) {
378-
iterator.remove();
379-
}
397+
try {
398+
Field field = type.getDeclaredField(fieldName);
399+
field.setAccessible(true);
400+
Object instance = field.get(null);
401+
if (instance instanceof Set) {
402+
((Set<?>) instance).clear();
403+
}
404+
if (instance instanceof Map) {
405+
Map<?, ?> map = ((Map<?, ?>) instance);
406+
for (Iterator<?> iterator = map.keySet().iterator(); iterator
407+
.hasNext();) {
408+
Object value = iterator.next();
409+
if (value instanceof Class && ((Class<?>) value)
410+
.getClassLoader() instanceof RestartClassLoader) {
411+
iterator.remove();
412+
}
380413

414+
}
381415
}
382416
}
417+
catch (Exception ex) {
418+
// Ignore
419+
}
383420
}
384421

385422
/**

0 commit comments

Comments
 (0)