If a SpEL expression references the root context object via the #root or #this variables, we currently insert a checkcast in the generated byte code that casts the object to its concrete type.

However if the root context object's type is non-public, that results in an IllegalAccessError when the compiled byte code is executed.

See the following test, for an example.

https://github.com/spring-projects/spring-framework/blob/a29c84f6637a42c9a6605a9bab752812bcba1205/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java#L514-L525

Interestingly enough, VariableReference.getValueInternal(ExpressionState) already contains a "workaround" for global variables which inserts a checkcast to Object in the generated byte code instead of to the object's concrete non-public type.

I have a local fix that applies the same logic to #root/#this and global variables. Thus, this issue is here to provide public visibility and raise awareness.