use of org.springframework.asm.ClassWriter in project spring-framework by spring-projects.
the class SpelCompiler method createExpressionClass.
/**
* Generate the class that encapsulates the compiled expression and define it.
* The generated class will be a subtype of CompiledExpression.
* @param expressionToCompile the expression to be compiled
* @return the expression call, or {@code null} if the decision was to opt out of
* compilation during code generation
*/
@Nullable
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile) {
// Create class outline 'spel/ExNNN extends org.springframework.expression.spel.CompiledExpression'
String className = "spel/Ex" + getNextSuffix();
String evaluationContextClass = "org/springframework/expression/EvaluationContext";
ClassWriter cw = new ExpressionClassWriter();
cw.visit(V1_8, ACC_PUBLIC, className, null, "org/springframework/expression/spel/CompiledExpression", null);
// Create default constructor
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "org/springframework/expression/spel/CompiledExpression", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
// Create getValue() method
mv = cw.visitMethod(ACC_PUBLIC, "getValue", "(Ljava/lang/Object;L" + evaluationContextClass + ";)Ljava/lang/Object;", null, new String[] { "org/springframework/expression/EvaluationException" });
mv.visitCode();
CodeFlow cf = new CodeFlow(className, cw);
// Ask the expression AST to generate the body of the method
try {
expressionToCompile.generateCode(mv, cf);
} catch (IllegalStateException ex) {
if (logger.isDebugEnabled()) {
logger.debug(expressionToCompile.getClass().getSimpleName() + ".generateCode opted out of compilation: " + ex.getMessage());
}
return null;
}
CodeFlow.insertBoxIfNecessary(mv, cf.lastDescriptor());
if ("V".equals(cf.lastDescriptor())) {
mv.visitInsn(ACONST_NULL);
}
mv.visitInsn(ARETURN);
// not supplied due to COMPUTE_MAXS
mv.visitMaxs(0, 0);
mv.visitEnd();
cw.visitEnd();
cf.finish();
byte[] data = cw.toByteArray();
// dump(expressionToCompile.toStringAST(), clazzName, data);
return loadClass(StringUtils.replace(className, "/", "."), data);
}
Aggregations