Skip to content

Illegal reflective access by SpEL ReflectivePropertyAccessor #22242

Closed
@ahagerup

Description

@ahagerup

This is technically a request to re-open SPR-17480 (JDK 11: Illegal reflective access by org.springframework.util.ReflectionUtils), since the problem has nothing to do with Thymeleaf.

Problem can be reproduced using Java 11.0.1 and Spring Expression 5.1.3.RELEASE with the following code:

	public class Test {
		public static void main(String[] args) {
			String expr = "entry.key";
			new SpelExpressionParser().parseExpression(expr).getValue(new Test());
		}
		public Map.Entry<String, String> getEntry() {
			return Map.of("foo", "bar").entrySet().iterator().next();
		}
	}

Running with --illegal-access=debug produces the following output:

	WARNING: Illegal reflective access by org.springframework.util.ReflectionUtils (file:/C:/Users/Andreas/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/5.1.3.RELEASE/b1e5325d35bfb27e42d57e9295510cad54ed8fdf/spring-core-5.1.3.RELEASE.jar) to method java.util.KeyValueHolder.getKey()
		at org.springframework.util.ReflectionUtils.makeAccessible(ReflectionUtils.java:499)
		at org.springframework.expression.spel.support.ReflectivePropertyAccessor$OptimalPropertyAccessor.read(ReflectivePropertyAccessor.java:691)
		at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:204)
		at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104)
		at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:51)
		at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:406)
		at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:90)
		at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:111)
		at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:201)
		at test.Test.main(Test.java:10)

The code in SPR-17480 tries to access java.util.HashMap$Node.getKey(), while the code above tries to access java.util.KeyValueHolder.getKey(), simply because a different Map implementation is used. The issue is the same.

The problem is that although the value returned by getEntry() is an interface with public methods (Map.Entry), the real object returned is a non-public class implementing the interface. Since the ReflectivePropertyAccessor logic resolves to the method of the non-public class, not to the method of the interface, ReflectionUtils.makeAccessible(Method method) ends up calling method.setAccessible(true).

Possible solution: Enhance ReflectivePropertyAccessor to search for the accessor method in public interfaces and public (super-)classes. Default to current logic if method cannot be located in a public type.

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions