-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Alvaro Manuel Recio Perez opened SPR-16255 and commented
We have issues in a scenario in which several threads are evaluating the same expression (which include functions) in IMMEDIATE mode.
org.springframework.expression.spel.standard.getValue() includes the following piece of code:
Object result = this.ast.getValue(expressionState);
checkCompile(expressionState);The call to checkCompile() goes through a synchronized block in compileExpression() which ends up in org.springframework.expression.spel.ast.FunctionReference.generateCode(). Inside this method, the field this.method is accessed twice, as follows:
@Override
public void generateCode(MethodVisitor mv,CodeFlow cf) {
Assert.state(this.method != null, "No method handle");
String classDesc = this.method.getDeclaringClass().getName().replace('.', '/');
generateCodeForArguments(mv, cf, this.method, this.children);
mv.visitMethodInsn(INVOKESTATIC, classDesc, this.method.getName(),
CodeFlow.createSignatureDescriptor(this.method), false);
cf.pushDescriptor(this.exitTypeDescriptor);
}However, the call to this.ast.getValue(expressionState) in org.springframework.expression.spel.standard.getValue() we saw earlier, which does not go through a synchronized block, ends up calling org.springframework.expression.spel.ast.FunctionReference.executeFunctionJLRMethod(). The first insruction of this method is:
private TypedValue executeFunctionJLRMethod(ExpressionState state, Method method) throws EvaluationException {
this.method = null;Because this code path is not synchronized, it may set this.method to null while the thread executing checkCompile() is running, causing a NullPointerException:
Exception in thread "Thread-95499" java.lang.NullPointerException
at org.springframework.expression.spel.ast.FunctionReference.generateCode(FunctionReference.java:184)
at org.springframework.expression.spel.standard.SpelCompiler.createExpressionClass(SpelCompiler.java:160)
at org.springframework.expression.spel.standard.SpelCompiler.compile(SpelCompiler.java:105)
at org.springframework.expression.spel.standard.SpelExpression.compileExpression(SpelExpression.java:467)
at org.springframework.expression.spel.standard.SpelExpression.checkCompile(SpelExpression.java:437)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:243)Affects: 4.3.13, 5.0.2
Referenced from: commits 6a1fe0b, a9bad58
Backported to: 4.3.14