Rename @CompileWithTargetClassAccess

Rename `@CompileWithTargetClassAccess` to
`@CompileWithForkedClassLoaderClassLoader`.

Closes gh-29173
This commit is contained in:
Phillip Webb 2022-09-19 09:37:36 -07:00
parent 7168141504
commit cc7552ec61
12 changed files with 37 additions and 36 deletions

View File

@ -27,7 +27,7 @@ import org.springframework.aot.generate.MethodReference;
import org.springframework.aot.generate.MethodReference.ArgumentCodeGenerator; import org.springframework.aot.generate.MethodReference.ArgumentCodeGenerator;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates; import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.aot.test.generate.TestGenerationContext; import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.aot.test.generate.compile.CompileWithTargetClassAccess; import org.springframework.aot.test.generate.compile.CompileWithForkedClassLoader;
import org.springframework.aot.test.generate.compile.Compiled; import org.springframework.aot.test.generate.compile.Compiled;
import org.springframework.aot.test.generate.compile.TestCompiler; import org.springframework.aot.test.generate.compile.TestCompiler;
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
@ -85,7 +85,7 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
} }
@Test @Test
@CompileWithTargetClassAccess @CompileWithForkedClassLoader
void contributeWhenPackagePrivateFieldInjectionInjectsUsingConsumer() { void contributeWhenPackagePrivateFieldInjectionInjectsUsingConsumer() {
Environment environment = new StandardEnvironment(); Environment environment = new StandardEnvironment();
this.beanFactory.registerSingleton("environment", environment); this.beanFactory.registerSingleton("environment", environment);
@ -122,7 +122,7 @@ class AutowiredAnnotationBeanRegistrationAotContributionTests {
} }
@Test @Test
@CompileWithTargetClassAccess @CompileWithForkedClassLoader
void contributeWhenPackagePrivateMethodInjectionInjectsUsingConsumer() { void contributeWhenPackagePrivateMethodInjectionInjectsUsingConsumer() {
Environment environment = new StandardEnvironment(); Environment environment = new StandardEnvironment();
this.beanFactory.registerSingleton("environment", environment); this.beanFactory.registerSingleton("environment", environment);

View File

@ -32,7 +32,7 @@ import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.generate.MethodReference; import org.springframework.aot.generate.MethodReference;
import org.springframework.aot.generate.MethodReference.ArgumentCodeGenerator; import org.springframework.aot.generate.MethodReference.ArgumentCodeGenerator;
import org.springframework.aot.test.generate.TestGenerationContext; import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.aot.test.generate.compile.CompileWithTargetClassAccess; import org.springframework.aot.test.generate.compile.CompileWithForkedClassLoader;
import org.springframework.aot.test.generate.compile.Compiled; import org.springframework.aot.test.generate.compile.Compiled;
import org.springframework.aot.test.generate.compile.TestCompiler; import org.springframework.aot.test.generate.compile.TestCompiler;
import org.springframework.aot.test.generate.file.SourceFile; import org.springframework.aot.test.generate.file.SourceFile;
@ -387,7 +387,7 @@ class BeanDefinitionMethodGeneratorTests {
} }
@Test @Test
@CompileWithTargetClassAccess @CompileWithForkedClassLoader
void generateBeanDefinitionMethodWhenPackagePrivateBean() { void generateBeanDefinitionMethodWhenPackagePrivateBean() {
RegisteredBean registeredBean = registerBean( RegisteredBean registeredBean = registerBean(
new RootBeanDefinition(PackagePrivateTestBean.class)); new RootBeanDefinition(PackagePrivateTestBean.class));

View File

@ -26,8 +26,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
/** /**
* Annotation that registers a JUnit Jupiter extension for test classes or test * Annotation that registers a JUnit Jupiter extension for test classes or test
* methods that need a {@link TestCompiler} with non-public access to target * methods that need to use a forked classloader with compiled code.
* classes.
* *
* <p>The extension allows the compiler to define classes without polluting the * <p>The extension allows the compiler to define classes without polluting the
* test {@link ClassLoader}. * test {@link ClassLoader}.
@ -45,6 +44,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD }) @Target({ ElementType.TYPE, ElementType.METHOD })
@Documented @Documented
@ExtendWith(CompileWithTargetClassAccessExtension.class) @ExtendWith(CompileWithForkedClassLoaderExtension.class)
public @interface CompileWithTargetClassAccess { public @interface CompileWithForkedClassLoader {
} }

View File

@ -26,29 +26,38 @@ import org.springframework.lang.Nullable;
/** /**
* {@link ClassLoader} implementation to support * {@link ClassLoader} implementation to support
* {@link CompileWithTargetClassAccess @CompileWithTargetClassAccess}. * {@link CompileWithForkedClassLoader @CompileWithForkedClassLoader}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Andy Wilkinson
* @author Stephane Nicoll
* @since 6.0 * @since 6.0
*/ */
final class CompileWithTargetClassAccessClassLoader extends ClassLoader { final class CompileWithForkedClassLoaderClassLoader extends ClassLoader {
private final ClassLoader testClassLoader; private final ClassLoader testClassLoader;
private Function<String, byte[]> classResourceLookup = name -> null; private Function<String, byte[]> classResourceLookup = name -> null;
public CompileWithTargetClassAccessClassLoader(ClassLoader testClassLoader) { public CompileWithForkedClassLoaderClassLoader(ClassLoader testClassLoader) {
super(testClassLoader.getParent()); super(testClassLoader.getParent());
this.testClassLoader = testClassLoader; this.testClassLoader = testClassLoader;
} }
// Invoked reflectively by DynamicClassLoader constructor // Invoked reflectively by DynamicClassLoader
@SuppressWarnings("unused") @SuppressWarnings("unused")
void setClassResourceLookup(Function<String, byte[]> classResourceLookup) { void setClassResourceLookup(Function<String, byte[]> classResourceLookup) {
this.classResourceLookup = classResourceLookup; this.classResourceLookup = classResourceLookup;
} }
// Invoked reflectively by DynamicClassLoader
@SuppressWarnings("unused")
Class<?> defineDynamicClass(String name, byte[] b, int off, int len) {
return super.defineClass(name, b, off, len);
}
@Override @Override
public Class<?> loadClass(String name) throws ClassNotFoundException { public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.startsWith("org.junit") || name.startsWith("org.testng")) { if (name.startsWith("org.junit") || name.startsWith("org.testng")) {
@ -82,13 +91,6 @@ final class CompileWithTargetClassAccessClassLoader extends ClassLoader {
return null; return null;
} }
// Invoked reflectively by DynamicClassLoader.findDefineClassMethod(ClassLoader)
@SuppressWarnings("unused")
Class<?> defineClassWithTargetAccess(String name, byte[] b, int off, int len) {
return super.defineClass(name, b, off, len);
}
@Override @Override
protected Enumeration<URL> findResources(String name) throws IOException { protected Enumeration<URL> findResources(String name) throws IOException {
return this.testClassLoader.getResources(name); return this.testClassLoader.getResources(name);

View File

@ -34,14 +34,14 @@ import static org.junit.platform.launcher.EngineFilter.includeEngines;
/** /**
* JUnit Jupiter {@link InvocationInterceptor} to support * JUnit Jupiter {@link InvocationInterceptor} to support
* {@link CompileWithTargetClassAccess @CompileWithTargetClassAccess}. * {@link CompileWithForkedClassLoader @CompileWithForkedClassLoader}.
* *
* @author Christoph Dreis * @author Christoph Dreis
* @author Phillip Webb * @author Phillip Webb
* @author Sam Brannen * @author Sam Brannen
* @since 6.0 * @since 6.0
*/ */
class CompileWithTargetClassAccessExtension implements InvocationInterceptor { class CompileWithForkedClassLoaderExtension implements InvocationInterceptor {
@Override @Override
public void interceptBeforeAllMethod(Invocation<Void> invocation, public void interceptBeforeAllMethod(Invocation<Void> invocation,
@ -105,7 +105,7 @@ class CompileWithTargetClassAccessExtension implements InvocationInterceptor {
Class<?> testClass = extensionContext.getRequiredTestClass(); Class<?> testClass = extensionContext.getRequiredTestClass();
ClassLoader classLoader = testClass.getClassLoader(); ClassLoader classLoader = testClass.getClassLoader();
return classLoader.getClass().getName() return classLoader.getClass().getName()
.equals(CompileWithTargetClassAccessClassLoader.class.getName()); .equals(CompileWithForkedClassLoaderClassLoader.class.getName());
} }
private void runTestWithModifiedClassPath( private void runTestWithModifiedClassPath(
@ -115,7 +115,7 @@ class CompileWithTargetClassAccessExtension implements InvocationInterceptor {
Class<?> testClass = extensionContext.getRequiredTestClass(); Class<?> testClass = extensionContext.getRequiredTestClass();
Method testMethod = invocationContext.getExecutable(); Method testMethod = invocationContext.getExecutable();
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
ClassLoader forkedClassPathClassLoader = new CompileWithTargetClassAccessClassLoader( ClassLoader forkedClassPathClassLoader = new CompileWithForkedClassLoaderClassLoader(
testClass.getClassLoader()); testClass.getClassLoader());
Thread.currentThread().setContextClassLoader(forkedClassPathClassLoader); Thread.currentThread().setContextClassLoader(forkedClassPathClassLoader);
try { try {

View File

@ -63,14 +63,14 @@ public class DynamicClassLoader extends ClassLoader {
this.classFiles = classFiles; this.classFiles = classFiles;
this.compiledClasses = compiledClasses; this.compiledClasses = compiledClasses;
Class<? extends ClassLoader> parentClass = parent.getClass(); Class<? extends ClassLoader> parentClass = parent.getClass();
if (parentClass.getName().equals(CompileWithTargetClassAccessClassLoader.class.getName())) { if (parentClass.getName().equals(CompileWithForkedClassLoaderClassLoader.class.getName())) {
Method setClassResourceLookupMethod = ReflectionUtils.findMethod(parentClass, Method setClassResourceLookupMethod = ReflectionUtils.findMethod(parentClass,
"setClassResourceLookup", Function.class); "setClassResourceLookup", Function.class);
ReflectionUtils.makeAccessible(setClassResourceLookupMethod); ReflectionUtils.makeAccessible(setClassResourceLookupMethod);
ReflectionUtils.invokeMethod(setClassResourceLookupMethod, ReflectionUtils.invokeMethod(setClassResourceLookupMethod,
getParent(), (Function<String, byte[]>) this::findClassBytes); getParent(), (Function<String, byte[]>) this::findClassBytes);
this.defineClassMethod = ReflectionUtils.findMethod(parentClass, this.defineClassMethod = ReflectionUtils.findMethod(parentClass,
"defineClassWithTargetAccess", String.class, byte[].class, int.class, int.class); "defineDynamicClass", String.class, byte[].class, int.class, int.class);
ReflectionUtils.makeAccessible(this.defineClassMethod); ReflectionUtils.makeAccessible(this.defineClassMethod);
this.compiledClasses.forEach((name, file) -> defineClass(name, file.getBytes())); this.compiledClasses.forEach((name, file) -> defineClass(name, file.getBytes()));
} }

View File

@ -276,7 +276,7 @@ public final class TestCompiler {
} }
catch (IllegalAccessError ex) { catch (IllegalAccessError ex) {
throw new IllegalAccessError(ex.getMessage() + ". " + throw new IllegalAccessError(ex.getMessage() + ". " +
"For non-public access ensure you annotate your test class or test method with @CompileWithTargetClassAccess"); "For non-public access ensure you annotate your test class or test method with @CompileWithForkedClassLoader");
} }
finally { finally {
Thread.currentThread().setContextClassLoader(previousClassLoader); Thread.currentThread().setContextClassLoader(previousClassLoader);

View File

@ -206,7 +206,7 @@ class TestCompilerTests {
} }
@Test @Test
@CompileWithTargetClassAccess @CompileWithForkedClassLoader
void compiledCodeCanAccessExistingPackagePrivateClassIfAnnotated() throws LinkageError { void compiledCodeCanAccessExistingPackagePrivateClassIfAnnotated() throws LinkageError {
SourceFiles sourceFiles = SourceFiles.of(SourceFile.of(""" SourceFiles sourceFiles = SourceFiles.of(SourceFile.of("""
package com.example; package com.example;
@ -240,7 +240,7 @@ class TestCompilerTests {
assertThatExceptionOfType(IllegalAccessError.class) assertThatExceptionOfType(IllegalAccessError.class)
.isThrownBy(() -> TestCompiler.forSystem().compile(sourceFiles, .isThrownBy(() -> TestCompiler.forSystem().compile(sourceFiles,
compiled -> compiled.getInstance(PublicInterface.class, "com.example.Test").perform())) compiled -> compiled.getInstance(PublicInterface.class, "com.example.Test").perform()))
.withMessageContaining(ClassUtils.getShortName(CompileWithTargetClassAccess.class)); .withMessageContaining(ClassUtils.getShortName(CompileWithForkedClassLoader.class));
} }
@Test @Test

View File

@ -34,7 +34,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.TypeReference; import org.springframework.aot.hint.TypeReference;
import org.springframework.aot.test.generate.TestGenerationContext; import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.aot.test.generate.compile.CompileWithTargetClassAccess; import org.springframework.aot.test.generate.compile.CompileWithForkedClassLoader;
import org.springframework.aot.test.generate.compile.Compiled; import org.springframework.aot.test.generate.compile.Compiled;
import org.springframework.aot.test.generate.compile.TestCompiler; import org.springframework.aot.test.generate.compile.TestCompiler;
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution; import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
@ -53,7 +53,7 @@ import static org.mockito.Mockito.mock;
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Phillip Webb * @author Phillip Webb
*/ */
@CompileWithTargetClassAccess @CompileWithForkedClassLoader
class PersistenceAnnotationBeanPostProcessorAotContributionTests { class PersistenceAnnotationBeanPostProcessorAotContributionTests {
private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

View File

@ -37,7 +37,7 @@ import org.opentest4j.MultipleFailuresError;
import org.springframework.aot.AotDetector; import org.springframework.aot.AotDetector;
import org.springframework.aot.generate.GeneratedFiles.Kind; import org.springframework.aot.generate.GeneratedFiles.Kind;
import org.springframework.aot.generate.InMemoryGeneratedFiles; import org.springframework.aot.generate.InMemoryGeneratedFiles;
import org.springframework.aot.test.generate.compile.CompileWithTargetClassAccess; import org.springframework.aot.test.generate.compile.CompileWithForkedClassLoader;
import org.springframework.aot.test.generate.compile.TestCompiler; import org.springframework.aot.test.generate.compile.TestCompiler;
import org.springframework.test.context.aot.samples.basic.BasicSpringJupiterSharedConfigTests; import org.springframework.test.context.aot.samples.basic.BasicSpringJupiterSharedConfigTests;
import org.springframework.test.context.aot.samples.basic.BasicSpringJupiterTests; import org.springframework.test.context.aot.samples.basic.BasicSpringJupiterTests;
@ -54,7 +54,7 @@ import static org.junit.platform.launcher.TagFilter.excludeTags;
* @author Sam Brannen * @author Sam Brannen
* @since 6.0 * @since 6.0
*/ */
@CompileWithTargetClassAccess @CompileWithForkedClassLoader
class AotIntegrationTests extends AbstractAotTests { class AotIntegrationTests extends AbstractAotTests {
private static final String CLASSPATH_ROOT = "AotSmokeTests.classpath_root"; private static final String CLASSPATH_ROOT = "AotSmokeTests.classpath_root";

View File

@ -33,7 +33,7 @@ import org.springframework.aot.generate.InMemoryGeneratedFiles;
import org.springframework.aot.hint.MemberCategory; import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.TypeReference; import org.springframework.aot.hint.TypeReference;
import org.springframework.aot.test.generate.compile.CompileWithTargetClassAccess; import org.springframework.aot.test.generate.compile.CompileWithForkedClassLoader;
import org.springframework.aot.test.generate.compile.TestCompiler; import org.springframework.aot.test.generate.compile.TestCompiler;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationContextInitializer;
@ -80,7 +80,7 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppC
* @author Sam Brannen * @author Sam Brannen
* @since 6.0 * @since 6.0
*/ */
@CompileWithTargetClassAccess @CompileWithForkedClassLoader
class TestContextAotGeneratorTests extends AbstractAotTests { class TestContextAotGeneratorTests extends AbstractAotTests {
/** /**

View File

@ -40,7 +40,7 @@
<suppress files="Target_ClassFinder" checks="HideUtilityClassConstructor"/> <suppress files="Target_ClassFinder" checks="HideUtilityClassConstructor"/>
<!-- spring-core-test --> <!-- spring-core-test -->
<suppress files="CompileWithTargetClassAccess" checks="IllegalImport" id="bannedJUnitJupiterImports" /> <suppress files="CompileWithForkedClassLoader" checks="IllegalImport" id="bannedJUnitJupiterImports" />
<suppress files="org[\\/]springframework[\\/]aot[\\/]test[\\/]agent[\\/].+" checks="IllegalImport" id="bannedJUnitJupiterImports" /> <suppress files="org[\\/]springframework[\\/]aot[\\/]test[\\/]agent[\\/].+" checks="IllegalImport" id="bannedJUnitJupiterImports" />
<!-- spring-expression --> <!-- spring-expression -->