Skip to content

ConfigurationClassEnhancer does not use correct ClassLoader when called multiple times #33024

Closed
@philwebb

Description

@philwebb

Discovered whilst looking into spring-projects/spring-boot#39733

The following test will pass with Spring Framework 5.3.36 but fail with Spring Framework 6.0.12:

package org.springframework.context.annotation;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;
import java.io.InputStream;
import java.security.SecureClassLoader;

import org.junit.jupiter.api.Test;
import org.springframework.util.StreamUtils;

class ConfigurationClassEnhancerTests {

	@Test
	void test() throws Exception {
		ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer();
		ClassLoader parentClassLoader = getClass().getClassLoader();
		MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
		Class<?> myClass = parentClassLoader.loadClass(MyConfig.class.getName());
		configurationClassEnhancer.enhance(myClass, parentClassLoader);
		Class<?> myReloadedClass = classLoader.loadClass(MyConfig.class.getName());
		Class<?> enhancedReloadedClass = configurationClassEnhancer.enhance(myReloadedClass, classLoader);
		assertThat(enhancedReloadedClass.getClassLoader()).isEqualTo(classLoader);
	}

	@Configuration
	static class MyConfig {

		@Bean
		public String myBean() {
			return "bean";
		}

	}

	static class MyClassLoader extends SecureClassLoader {

		MyClassLoader(ClassLoader parent) {
			super(parent);
		}

		protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
			if (name.contains("MyConfig")) {
				String path = name.replace('.', '/').concat(".class");
				try (InputStream in = super.getResourceAsStream(path)) {
					byte[] bytes = StreamUtils.copyToByteArray(in);
					if (bytes.length > 0) {
						return defineClass(name, bytes, 0, bytes.length);
					}
				} catch (IOException ex) {
					throw new IllegalStateException(ex);
				}
			}
			return super.loadClass(name, resolve);
		}

	}

}

I haven't managed to exactly track down why, but I suspect that b31a158 might have introduced the problem. Perhaps this key?

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)status: backportedAn issue that has been backported to maintenance branchestype: regressionA bug that is also a regression

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions