spring-projects/spring-framework · error · IllegalStateException

Failed to load Class [

Error message

Failed to load Class [

What it means

Thrown as an IllegalStateException during AOT code generation when a bean's init/destroy method name is fully qualified (contains a '.' specifying a declaring class other than the bean class) and ClassUtils.forName cannot load that class through the bean class's ClassLoader. The generator (BeanDefinitionPropertiesCodeGenerator.addInitDestroyHint) parses the prefix off the method name to register a reflection hint on the real declaring class; if that class is absent from the classpath/native-image, generation aborts.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionPropertiesCodeGenerator.java:182

					.collect(CodeBlock.joining(", "));
			code.addStatement(format, BEAN_DEFINITION_VARIABLE, arguments);
		}
	}

	private void addInitDestroyHint(Class<?> beanUserClass, String methodName) {
		Class<?> methodDeclaringClass = beanUserClass;

		// Parse fully-qualified method name if necessary.
		int indexOfDot = methodName.lastIndexOf('.');
		if (indexOfDot > 0) {
			String className = methodName.substring(0, indexOfDot);
			methodName = methodName.substring(indexOfDot + 1);
			if (!beanUserClass.getName().equals(className)) {
				try {
					methodDeclaringClass = ClassUtils.forName(className, beanUserClass.getClassLoader());
				}
				catch (Throwable ex) {
					throw new IllegalStateException("Failed to load Class [" + className +
							"] from ClassLoader [" + beanUserClass.getClassLoader() + "]", ex);
				}
			}
		}

		Method method = ReflectionUtils.findMethod(methodDeclaringClass, methodName);
		if (method != null) {
			this.hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
			Method publiclyAccessibleMethod = ClassUtils.getPubliclyAccessibleMethodIfPossible(method, beanUserClass);
			if (!publiclyAccessibleMethod.equals(method)) {
				this.hints.reflection().registerMethod(publiclyAccessibleMethod, ExecutableMode.INVOKE);
			}
		}
	}

	private void addConstructorArgumentValues(CodeBlock.Builder code, BeanDefinition beanDefinition) {
		ConstructorArgumentValues constructorValues = beanDefinition.getConstructorArgumentValues();
		Map<Integer, ValueHolder> indexedValues = constructorValues.getIndexedArgumentValues();

View on GitHub (pinned to 69bf83ad71)

Solutions

  1. Make sure the fully-qualified class used as the init/destroy method prefix is on the AOT build classpath and reachable by the bean's ClassLoader.
  2. If the method actually lives on the bean class itself, remove the class prefix and specify just the method name.
  3. Fix the typo or stale FQN in the XML init-method/destroy-method attribute or @Bean(initMethod=...) / destroyMethod.
  4. If the class is intentionally optional, register a substitute init/destroy method that does not reference it, or guard the bean definition so it isn't processed when the class is absent.
  5. Run the native build with --debug to see the exact class name and ClassLoader that failed, then add the missing artifact as a dependency.

Example fix

// before: prefix class missing from native image
@Bean(initMethod = "com.acme.legacy.Lifecycle.start")
public MyBean myBean() { ... }

// after: method on the bean class itself, no FQN prefix
@Bean(initMethod = "start")
public MyBean myBean() { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Validate a fully-qualified init/destroy method before AOT runs
String m = "com.acme.Helper.init";
int dot = m.lastIndexOf('.');
if (dot <= 0) throw new IllegalArgumentException("Bad method spec: " + m);
Class<?> cls = ClassUtils.forName(m.substring(0, dot), beanClassLoader);
Assert.notNull(ReflectionUtils.findMethod(cls, m.substring(dot + 1)),
    () -> "Method not found: " + m);

Prevention

When it happens

Trigger: A bean definition carries an init-method or destroy-method value like 'com.acme.Helper.init' where 'com.acme.Helper' is not resolvable by the bean class's ClassLoader at AOT build time. Triggered when BeanDefinitionPropertiesCodeGenerator is generating the bean-definition properties code and the prefix class load fails.

Common situations: Specifying an init/destroy method on a class that lives in an optional dependency not on the AOT classpath; renaming/moving the helper class without updating XML or @Bean(initMethod=...) values; GraalVM native-image build pruning a class that is only referenced by string in a method name; multi-module build where the module containing the declaring class is not on the compile classpath.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/58f49d1d83316c79. Report an issue: GitHub.