spring-projects/spring-framework · error · AopInvocationException

Could not access method

Error message

Could not access method [{method}]

What it means

Thrown by AopUtils.invokeJoinpointUsingReflection (line 370-372) when Method.invoke fails with IllegalAccessException or InaccessibleObjectException after ReflectionUtils.makeAccessible was attempted. The method could not be made accessible - classically due to Java Platform Module System strong encapsulation (a type in a non-exported package) or a SecurityManager/deny policy blocking reflective access. The original exception is wrapped in an AopInvocationException.

Solutions

  1. If the class is in your own module, add 'opens your.package to spring.core spring.aop;' (or 'opens ... to ALL-UNNAMED') in module-info.
  2. On the command line, add '--add-opens your.module/your.package=ALL-UNNAMED' to allow reflective access.
  3. Make the method/package-accessible (public, or in an exported/open package) so no suppression is required.
  4. If a SecurityManager is present, grant ReflectPermission 'suppressAccessChecks' to the application codebase.

Example fix

// before (Java 17, advised bean in unopened module)
module my.app { exports com.example; } // not opened
// -> IllegalAccessException on makeAccessible

// after
module my.app {
    exports com.example;
    opens com.example to spring.aop; // or ALL-UNNAMED
}
Defensive patterns

Strategy: validation

Validate before calling

try {
    ReflectionUtils.makeAccessible(method);
} catch (InaccessibleObjectException e) {
    // package not opened; instruct user to add --add-opens / 'opens' directive
}

Try / catch

try {
    return method.invoke(target, args);
} catch (IllegalAccessException | InaccessibleObjectException e) {
    // surface a clear message about JPMS 'opens' / module access
    throw new IllegalStateException(
        "Method " + method + " is inaccessible; open its package to the application module", e);
}

Prevention

When it happens

Trigger: Advising a method on a class in a module whose package is not 'opens' to the application, on Java 16+ where strong encapsulation is enforced by default and makeAccessible is denied. Also when a custom SecurityManager forbids suppressAccessChecks, or the method's class loader is isolated.

Common situations: Java 16+ modules: an advised bean lives in a library module that does not 'opens' its package to Spring. Accessing JDK internal classes via AOP. Running with a SecurityManager that denies ReflectPermission('suppressAccessChecks'). Upgrading from Java 8/11 to 17 where illegal reflective access is blocked outright.

Related errors


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

Appendix: source

Thrown at spring-aop/src/main/java/org/springframework/aop/support/AopUtils.java:371

		// Use reflection to invoke the method.
		try {
			Method originalMethod = BridgeMethodResolver.findBridgedMethod(method);
			ReflectionUtils.makeAccessible(originalMethod);
			return (COROUTINES_REACTOR_PRESENT && KotlinDetector.isSuspendingFunction(originalMethod) ?
					KotlinDelegate.invokeSuspendingFunction(originalMethod, target, args) : originalMethod.invoke(target, args));
		}
		catch (InvocationTargetException ex) {
			// Invoked method threw a checked exception.
			// We must rethrow it. The client won't see the interceptor.
			throw ex.getTargetException();
		}
		catch (IllegalArgumentException ex) {
			throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
					method + "] on target [" + target + "]", ex);
		}
		catch (IllegalAccessException | InaccessibleObjectException ex) {
			throw new AopInvocationException("Could not access method [" + method + "]", ex);
		}
	}


	/**
	 * Inner class to avoid a hard dependency on Kotlin at runtime.
	 */
	private static class KotlinDelegate {

		public static Object invokeSuspendingFunction(Method method, @Nullable Object target, @Nullable Object... args) {
			Continuation<?> continuation = (Continuation<?>) args[args.length -1];
			Assert.state(continuation != null, "No Continuation available");
			CoroutineContext context = continuation.getContext().minusKey(Job.Key);
			return CoroutinesUtils.invokeSuspendingFunction(context, method, target, args);
		}
	}

}

View on GitHub (pinned to 69bf83ad71)