Commit dc75ca39 authored by Andy Wilkinson's avatar Andy Wilkinson

Avoid capturing TCCL when creating DefaultResourceLoaders

Previously, DefaultResourceLoader instances were created using the
default constructor. This causes the resource loader to capture the
TCCL that was in place at that time. This can lead to a class loader
leak if the resource loader is referenced directly or indirectly from
a static field of a class loaded by a different class loader.

This commit updates the creation of DefaultResourceLoader instances
in main code so that the resource load will use the class loader of
the creating class. In almost all cases this will be the same class
loader as was the thread context class loader that was being captured
so the change in behavior is minimal. Crucially, it will still address
the situation where the TCCL was different.

Note the DevTools' ApplicationContextResourceLoader has been updated
to explicitly use the TCCL. This ensures that it uses the restart
class loader which is required for DevTools to function correctly.

Fixes gh-20900
parent d53be185
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -67,7 +67,8 @@ class DataSourceInitializer {
DataSourceInitializer(DataSource dataSource, DataSourceProperties properties, ResourceLoader resourceLoader) {
this.dataSource = dataSource;
this.properties = properties;
this.resourceLoader = (resourceLoader != null) ? resourceLoader : new DefaultResourceLoader();
this.resourceLoader = (resourceLoader != null) ? resourceLoader
: new DefaultResourceLoader(getClass().getClassLoader());
}
/**
......
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -47,7 +47,7 @@ public class MustacheResourceTemplateLoader implements TemplateLoader, ResourceL
private String charSet = "UTF-8";
private ResourceLoader resourceLoader = new DefaultResourceLoader();
private ResourceLoader resourceLoader = new DefaultResourceLoader(getClass().getClassLoader());
public MustacheResourceTemplateLoader() {
}
......
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -238,6 +238,8 @@ final class ClassLoaderFilesResourcePatternResolver implements ResourcePatternRe
private final Supplier<Collection<ProtocolResolver>> protocolResolvers;
ApplicationContextResourceLoader(Supplier<Collection<ProtocolResolver>> protocolResolvers) {
// Use the restart class loader
super(Thread.currentThread().getContextClassLoader());
this.protocolResolvers = protocolResolvers;
}
......
......@@ -320,7 +320,8 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
this.environment = environment;
this.placeholdersResolver = new PropertySourcesPlaceholdersResolver(this.environment);
this.resourceLoader = (resourceLoader != null) ? resourceLoader : new DefaultResourceLoader();
this.resourceLoader = (resourceLoader != null) ? resourceLoader
: new DefaultResourceLoader(getClass().getClassLoader());
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
getClass().getClassLoader());
this.patternResolver = new PathMatchingResourcePatternResolver(this.resourceLoader);
......
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -33,7 +33,8 @@ import org.springframework.util.ResourceUtils;
*/
class StringToFileConverter implements Converter<String, File> {
private static final ResourceLoader resourceLoader = new DefaultResourceLoader();
private static final ResourceLoader resourceLoader = new DefaultResourceLoader(
StringToFileConverter.class.getClassLoader());
@Override
public File convert(String source) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment