Aviator源码:Aviator表达式引擎执行过程源码分析

article/2025/10/24 0:01:57

目录

1.if执行脚本示例

2.源码分析

2.1 compile执行过程

2.1.1 CodeGenerator

2.1.2 ExpressionParser

2.1.3 if脚本ASM反编译结果

2.2 compiledExpression.execute执行过程

3.总结概述


由于Aviator支持的脚本语法较多,下面通过项目中使用较多的if语句来对aviator执行过程进行一次源码剖析,以便更清楚的了解aviator具体的解析执行过程,并加深技术储备,方便后续aviator源码相关问题的快速深入分析,同时希望达到“窥一斑而知全貌”的效果;

1.if执行脚本示例

Map<String, Object> env = new HashMap<>();
env.put("a", 2);
env.put("b", 3);
env.put("c", 4);
Object result = AviatorEvaluator.execute("if(a > 1) { return b+2; } else { return c; }", env);

通过执行上述的if脚本,着重分析aviator框架内部的解析逻辑,比如通过asm字节码技术动态生成class、LambdaFunctionBootstrap构造和设计理念以及LambdaFunction函数的构造和设计理念等;

2.源码分析

跟踪AviatorEvaluator.execute方法,内部实现如下:

  /*** Execute a text expression with environment** @param cacheKey unique key for caching* @param expression text expression* @param env Binding variable environment* @param cached Whether to cache the compiled result,make true to cache it.*/public Object execute(final String cacheKey, final String expression,final Map<String, Object> env, final boolean cached) {Expression compiledExpression = compile(cacheKey, expression, cached);if (compiledExpression != null) {return compiledExpression.execute(env);} else {throw new ExpressionNotFoundException("Null compiled expression for " + expression);}}

其中主要包含2个部分:

1)compile方法通过asm技术生成ClassExpression的子类:这里将整个表达式脚本编译为ClassExpression子类;

2)执行compiledExpression.execute方法:将外部传入的变量集env实参带入方法中进行执行,返回脚本执行结果;

下面对这2个部分分别进行分析:

2.1 compile执行过程

compile方法体中使用了LRU或HashMap对编译后的字节码进行缓存,编译的字节码是通过方法innerCompile来获取的:

 private Expression compile(final String cacheKey, final String expression,final String sourceFile, final boolean cached) {if (expression == null || expression.trim().length() == 0) {throw new CompileExpressionErrorException("Blank expression");}if (cacheKey == null || cacheKey.trim().length() == 0) {throw new CompileExpressionErrorException("Blank cacheKey");}if (cached) {FutureTask<Expression> existedTask = null;if (this.expressionLRUCache != null) {boolean runTask = false;synchronized (this.expressionLRUCache) {existedTask = this.expressionLRUCache.get(cacheKey);if (existedTask == null) {existedTask = newCompileTask(expression, sourceFile, cached);runTask = true;this.expressionLRUCache.put(cacheKey, existedTask);}}if (runTask) {existedTask.run();}} else {FutureTask<Expression> task = this.expressionCache.get(cacheKey);if (task != null) {return getCompiledExpression(expression, task);}task = newCompileTask(expression, sourceFile, cached);existedTask = this.expressionCache.putIfAbsent(cacheKey, task);if (existedTask == null) {existedTask = task;existedTask.run();}}return getCompiledExpression(cacheKey, existedTask);} else {return innerCompile(expression, sourceFile, cached);}}

innerCompile方法实现如下:

  private Expression innerCompile(final String expression, final String sourceFile,final boolean cached) {ExpressionLexer lexer = new ExpressionLexer(this, expression);CodeGenerator codeGenerator = newCodeGenerator(sourceFile, cached);ExpressionParser parser = new ExpressionParser(this, lexer, codeGenerator);Expression exp = parser.parse();if (getOptionValue(Options.TRACE_EVAL).bool) {((BaseExpression) exp).setExpression(expression);}return exp;}

这里说明几个主要用到的类:

ExpressionLexer:表达式词法分析器,用来对aviator脚本进行词法解析,如将脚本解析为变量、数字、字符串、注释等,并构造Token流进行后续处理;

CodeGenerator:字节码生成器,用于动态生成自定义的字节码;

ExpressionParser:表达式解析器,用于将脚本编译为表达式对象(ClassExpression),支持对多种aviator支持的脚本进行解析,具体解析过程是将ExpressionLexer构造的Token流通过字节码生成器编译为表达式对象ClassExpression

2.1.1 CodeGenerator

这里用到的CodeGenerator主要包括:

CodeGenerator:定义了字节码生成的顶层接口

ASMCodeGenerator:默认的ASM字节码生成器,对CodeGenerator声明的操作进行ASM具体实现

OptimizeCodeGenerator:为加快执行效率而生的字节码生成器(默认的字节码生成器),可以执行一些前置的计算逻辑,然后再委托ASMCodeGenerator进行字节码生成

2.1.2 ExpressionParser

ExpressionParser完成对多种aviator支持的脚本的解析工作,比如if,for,let等脚本特性,解析逻辑是依赖parse方法完成的,如下:

  public Expression parse(final boolean reportErrorIfNotEOF) {StatementType statementType = statements();if (this.lookhead != null && reportErrorIfNotEOF) {if (statementType == StatementType.Ternary) {reportSyntaxError("unexpect token '" + currentTokenLexeme()+ "', maybe forget to insert ';' to complete last expression ");} else {reportSyntaxError("unexpect token '" + currentTokenLexeme() + "'");}}return getCodeGeneratorWithTimes().getResult(true);}

这里主要分为2个部分:

1)调用statements完成脚本解析工作,产出Token流(以默认的OptimizeCodeGenerator进行分析)

2)调用OptimizeCodeGenerator的getResult方法完成ASM字节码生成,并根据字节码构造完成ClassExpression实例对象

2.1.1.1 statements方法

statements中主要的解析过程如下:

private StatementType statements() {if (this.lookhead == null) {return StatementType.Empty;}StatementType stmtType = statement();ensureDepthState();while (expectChar(';') || stmtType == StatementType.Other || stmtType == StatementType.Return) {ensureNoStatementAfterReturn(stmtType);if (this.lookhead != null && this.lookhead != Variable.END && !expectChar('}')) {getCodeGeneratorWithTimes().onTernaryEnd(this.lookhead);}if (expectChar(';')) {move(true);}if (this.lookhead == null) {break;}StatementType nextStmtType = statement();if (nextStmtType == StatementType.Empty) {break;}stmtType = nextStmtType;ensureDepthState();}ensureNoStatementAfterReturn(stmtType);// If the last statement is ternary,it must be ended with END TOKEN such as null token, '}',// 'end' keyword, or ';'// Otherwise report syntax error.if (stmtType == StatementType.Ternary) {if (lookhead != null && !expectChar(';') && !expectChar('}') && lookhead != Variable.END) {this.back();reportSyntaxError("unexpect token '" + currentTokenLexeme()+ "', maybe forget to insert ';' to complete last expression ");}}return stmtType;}

具体的解析过程是在statement方法中,如下:

private StatementType statement() {if (this.lookhead == Variable.IF) {ensureFeatureEnabled(Feature.If);if (ifStatement(false, false)) {return StatementType.Return;} else {return StatementType.Other;}} else if (this.lookhead == Variable.FOR) {ensureFeatureEnabled(Feature.ForLoop);forStatement();return StatementType.Other;} else if (this.lookhead == Variable.RETURN) {ensureFeatureEnabled(Feature.Return);returnStatement();return StatementType.Return;} else if (this.lookhead == Variable.BREAK) {breakStatement();return StatementType.Return;} else if (this.lookhead == Variable.CONTINUE) {continueStatement();return StatementType.Return;} else if (this.lookhead == Variable.LET) {ensureFeatureEnabled(Feature.Let);letStatement();return StatementType.Other;} else if (this.lookhead == Variable.WHILE) {ensureFeatureEnabled(Feature.WhileLoop);whileStatement();return StatementType.Other;} else if (this.lookhead == Variable.FN) {ensureFeatureEnabled(Feature.Fn);fnStatement();return StatementType.Other;} else if (this.lookhead == Variable.TRY) {ensureFeatureEnabled(Feature.ExceptionHandle);tryStatement();return StatementType.Other;} else if (this.lookhead == Variable.THROW) {ensureFeatureEnabled(Feature.ExceptionHandle);throwStatement();return StatementType.Other;} else if (expectChar('{')) {ensureFeatureEnabled(Feature.LexicalScope);if (scopeStatement()) {return StatementType.Return;} else {return StatementType.Other;}} else if (this.lookhead == Variable.USE) {ensureFeatureEnabled(Feature.Use);useStatement();return StatementType.Other;} else {if (ternary()) {return StatementType.Ternary;} else {return StatementType.Empty;}}}

这里可以看到:aviator支持的多种脚本特性,比如if、for、let、return等语法都是在这里解析完成的;

以if语法举例说明,继续跟踪ifStatement方法,如下:

  /*** <pre>*  if(test) {*     ...if-body...*  }else {*     ...else-body...*  }*  ...statements...* </pre>** ===>** <pre>*  __if_callcc(test ? (lambda() -> ...if-body... end)() :  (lambda() -> ...else-body... end)(),*   lambda()- >*       ...statements...*  end);* </pre>*/private boolean ifStatement(final boolean isWhile, final boolean isElsif) {if (!isWhile) {move(true);}boolean ifBodyHasReturn = false;boolean elseBodyHasReturn = false;boolean newLexicalScope = this.scope.newLexicalScope;this.scope.newLexicalScope = true;// prepare to call __if_callcc(result, statements)getCodeGeneratorWithTimes().onMethodName(Constants.IfReturnFn);{if (!ternary()) {reportSyntaxError("missing test statement for if");}getCodeGeneratorWithTimes().onTernaryBoolean(this.lookhead);if (expectChar('{')) {move(true);this.scope.enterBrace();getCodeGeneratorWithTimes().onLambdaDefineStart(getPrevToken().withMeta(Constants.SCOPE_META, this.scope.newLexicalScope));getCodeGeneratorWithTimes().onLambdaBodyStart(this.lookhead);ifBodyHasReturn = statements() == StatementType.Return;getCodeGeneratorWithTimes().onLambdaBodyEnd(this.lookhead);getCodeGeneratorWithTimes().onMethodName(anonymousMethodName());getCodeGeneratorWithTimes().onMethodInvoke(this.lookhead);getCodeGeneratorWithTimes().onTernaryLeft(this.lookhead);} else {reportSyntaxError("expect '{' for " + getLoopKeyword(isWhile) + " statement");}if (!expectChar('}')) {reportSyntaxError("missing '}' to close " + getLoopKeyword(isWhile) + " body");}this.scope.leaveBrace();move(true);elseBodyHasReturn = elseStatement(isWhile, ifBodyHasReturn);getCodeGeneratorWithTimes().onMethodParameter(this.lookhead);}{//if (isWhile || isElsif) {// Load ReducerEmptyVal directly.getCodeGenerator().onConstant(Constants.ReducerEmptyVal);} else {if (expectChar(';')) {// the statement is ended.getCodeGenerator().onConstant(Constants.ReducerEmptyVal);} else {// create a lambda function wraps statements after if statement (statements)getCodeGeneratorWithTimes().onLambdaDefineStart(getPrevToken().withMeta(Constants.SCOPE_META, this.scope.newLexicalScope) //.withMeta(Constants.INHERIT_ENV_META, true));getCodeGeneratorWithTimes().onLambdaBodyStart(this.lookhead);if (statements() == StatementType.Empty) {getCodeGenerator().onConstant(Constants.ReducerEmptyVal);} else {if (ifBodyHasReturn && elseBodyHasReturn && !isElsif) {reportSyntaxError("unreachable code");}}getCodeGeneratorWithTimes().onLambdaBodyEnd(this.lookhead);}}getCodeGenerator().onMethodParameter(this.lookhead);// call __if_callcc(result, statements)getCodeGenerator().onMethodInvoke(this.lookhead);this.scope.newLexicalScope = newLexicalScope;}return ifBodyHasReturn && elseBodyHasReturn;}

if语法的解析过程主要分为以下几个部分:

1)通过ternary方法完成对if条件语句的解析(解析结果放入OptimizeCodeGenerator的Token流中,后续统一生成字节码)

2)if的方法体(ifBody)抽象为一个lambda表达式,并通过委托给lambdaGenerator进行解析,后面着重分析该解析过程;

3)对elseBody进行解析:这里实际的解析过程和ifBody的解析过程类似,也是委托给新构建的lambdaGenerator进行解析;

 private boolean elseStatement(final boolean isWhile, final boolean ifBodyHasReturn) {if (isWhile) {// Call __reducer_break(nil)final CodeGenerator cg = getCodeGeneratorWithTimes();cg.onMethodName(Constants.ReducerBreakFn);cg.onConstant(Variable.NIL);cg.onMethodParameter(this.lookhead);cg.onMethodInvoke(this.lookhead);cg.onTernaryRight(this.lookhead);return false;}if (expectChar(';')) {return withoutElse();}boolean hasReturn = false;boolean hasElsif = this.lookhead == Variable.ELSIF;boolean hasElse = this.lookhead == Variable.ELSE;if (this.lookhead != null && (hasElse || hasElsif || ifBodyHasReturn)) {if (hasElse) {move(true);if (expectChar('{')) {this.scope.enterBrace();move(true);hasReturn = elseBody(false);if (expectChar('}')) {this.scope.leaveBrace();move(true);} else {reportSyntaxError("missing '}' to close 'else' body");}} else {reportSyntaxError("expect '{' for else statement");}} else if (hasElsif) {hasReturn = ifStatement(false, true);getCodeGenerator().onTernaryRight(this.lookhead);} else if (ifBodyHasReturn) {hasReturn = elseBody(true);} else {return withoutElse();}return hasReturn;} else {// Missing else statement, always nil.return withoutElse();}}

4)这里对if语句后面的整个脚本抽象为一个lambda表达式,也是通过委托给lambdaGenerator进行解析;

如上的解析过程也可以借助方法注释进行较好的理解:

2.1.1.1.1 lambdaGenerator解析过程分析

对2.1.1.1 节的注释2的代码进一步分析:

1)lambda脚本解析前置环节

onLambdaDefineStart方法构造lambdaGenerator;

onLambdaBodyStart方法将ExpressionParser的codeGenerator替换为新构造的lambdaGenerator,同时维护好lambdaGenerator的父parentCodeGenerator=OptimizeCodeGenerator,lamdba解析完成后再替换回parentCodeGenerator,也即OptimizeCodeGenerator,也及整个脚本的ASM操作是通过OptimizeCodeGenerator和lambdaGenerator(如果包含lambda语法)交替完成的

2)lambda脚本解析完成后

lambda脚本解析完成后,这里会调用getLmabdaBootstrap构造LambdaFunctionBootstrap实例对象,并将LambdaFunctionBootstrap缓存到OptimizeCodeGenerator的

Map<String, LambdaFunctionBootstrap> lambdaBootstraps成员变量中;

进一步展开getLmabdaBootstrap函数:

可以看到这里也是通过getResult方法通过ASM字节码技术动态构造Expression子类实例(具体分析过程见2.1.1.2),构造的结果放到了LambdaFunctionBootstrap实例对象中,也即lambda表达式的解析结果即为LambdaFunctionBootstrap;

2.1.1.2 OptimizeCodeGenerator.getResult()过程分析

aviator脚本解析完成之后,解析结果Token流会存放到OptimizeCodeGenerator的成员变量List<Token<?>> tokenList中,getResult方法就是根据tokenList生成字节码的过程;

getResult方法具体实现如下:

  @Overridepublic Expression getResult(final boolean unboxObject) {// execute literal expressionwhile (execute() > 0) {;}Map<String, VariableMeta/* metadata */> variables = new LinkedHashMap<String, VariableMeta>();Map<String, Integer/* counter */> methods = new HashMap<String, Integer>();Set<Token<?>> constants = new HashSet<>();for (Token<?> token : this.tokenList) {if (ExpressionParser.isConstant(token, this.instance)) {constants.add(token);}switch (token.getType()) {case Variable:if (SymbolTable.isReservedKeyword((Variable) token)) {continue;}String varName = token.getLexeme();VariableMeta meta = variables.get(varName);if (meta == null) {meta = new VariableMeta((CompileTypes) token.getMeta(Constants.TYPE_META), varName,token.getMeta(Constants.INIT_META, false), token.getStartIndex());variables.put(varName, meta);} else {meta.add(token);}break;case Delegate:DelegateToken delegateToken = (DelegateToken) token;if (delegateToken.getDelegateTokenType() == DelegateTokenType.Method_Name) {Token<?> realToken = delegateToken.getToken();if (realToken == null) {continue;}if (realToken.getType() == TokenType.Variable) {String methodName = token.getLexeme();if (!methods.containsKey(methodName)) {methods.put(methodName, 1);} else {methods.put(methodName, methods.get(methodName) + 1);}}} else if (delegateToken.getDelegateTokenType() == DelegateTokenType.Array) {Token<?> realToken = delegateToken.getToken();if (realToken.getType() == TokenType.Variable) {varName = token.getLexeme();VariableMeta varMeta = variables.get(varName);if (varMeta == null) {varMeta =new VariableMeta((CompileTypes) realToken.getMeta(Constants.TYPE_META), varName,realToken.getMeta(Constants.INIT_META, false), realToken.getStartIndex());variables.put(varName, varMeta);} else {varMeta.add(realToken);}}}break;}}Expression exp = null;// Last token is a literal token,then return a LiteralExpressionif (this.tokenList.size() <= 1) {if (this.tokenList.isEmpty()) {exp = new LiteralExpression(this.instance, null, new ArrayList<>(variables.values()));} else {final Token<?> lastToken = this.tokenList.get(0);if (ExpressionParser.isLiteralToken(lastToken, this.instance)) {exp = new LiteralExpression(this.instance,getAviatorObjectFromToken(lastToken).getValue(getCompileEnv()),new ArrayList<>(variables.values()));}}}if (exp == null) {// call asm to generate byte codescallASM(variables, methods, constants);// get result from asmexp = this.codeGen.getResult(unboxObject);}if (exp instanceof BaseExpression) {((BaseExpression) exp).setCompileEnv(getCompileEnv());((BaseExpression) exp).setSourceFile(this.sourceFile);}return exp;}

这里主要包含以下几部分:

1)可以前置执行的逻辑提前执行,比如文本表达式(1+2)等,先行计算出执行结果,优化执行效率;

2)初始化常量集、变量集、aviator函数实例集合,为后续ASM生成类成员变量和类构造函数使用;

3)调用callASM方法生成字节码,根据不同的token类型进行不同的asm操作;

 private void callASM(final Map<String, VariableMeta/* metadata */> variables,final Map<String, Integer/* counter */> methods, final Set<Token<?>> constants) {this.codeGen.initConstants(constants);this.codeGen.initVariables(variables);this.codeGen.initMethods(methods);this.codeGen.setLambdaBootstraps(this.lambdaBootstraps);this.codeGen.start();for (int i = 0; i < this.tokenList.size(); i++) {Token<?> token = this.tokenList.get(i);switch (token.getType()) {case Operator:OperatorToken op = (OperatorToken) token;switch (op.getOperatorType()) {case ADD:this.codeGen.onAdd(token);break;case SUB:this.codeGen.onSub(token);break;case MULT:this.codeGen.onMult(token);break;case Exponent:this.codeGen.onExponent(token);break;case DIV:this.codeGen.onDiv(token);break;case MOD:this.codeGen.onMod(token);break;case EQ:this.codeGen.onEq(token);break;case NEQ:this.codeGen.onNeq(token);break;case LT:this.codeGen.onLt(token);break;case LE:this.codeGen.onLe(token);break;case GT:this.codeGen.onGt(token);break;case GE:this.codeGen.onGe(token);break;case NOT:this.codeGen.onNot(token);break;case NEG:this.codeGen.onNeg(token);break;case AND:this.codeGen.onAndRight(token);break;case OR:this.codeGen.onJoinRight(token);break;case FUNC:this.codeGen.onMethodInvoke(token);break;case INDEX:this.codeGen.onArrayIndexEnd(token);break;case MATCH:this.codeGen.onMatch(token);break;case TERNARY:this.codeGen.onTernaryRight(token);break;case BIT_AND:this.codeGen.onBitAnd(token);break;case BIT_OR:this.codeGen.onBitOr(token);break;case BIT_XOR:this.codeGen.onBitXor(token);break;case BIT_NOT:this.codeGen.onBitNot(token);break;case SHIFT_LEFT:this.codeGen.onShiftLeft(token);break;case SHIFT_RIGHT:this.codeGen.onShiftRight(token);break;case DEFINE:this.codeGen.onAssignment(token.withMeta(Constants.DEFINE_META, true));break;case ASSIGNMENT:this.codeGen.onAssignment(token);break;case U_SHIFT_RIGHT:this.codeGen.onUnsignedShiftRight(token);break;}break;case Delegate:DelegateToken delegateToken = (DelegateToken) token;final Token<?> realToken = delegateToken.getToken();switch (delegateToken.getDelegateTokenType()) {case And_Left:this.codeGen.onAndLeft(realToken);break;case Join_Left:this.codeGen.onJoinLeft(realToken);break;case Array:this.codeGen.onArray(realToken);break;case Index_Start:this.codeGen.onArrayIndexStart(realToken);break;case Ternary_Boolean:this.codeGen.onTernaryBoolean(realToken);break;case Ternary_Left:this.codeGen.onTernaryLeft(realToken);break;case Method_Name:this.codeGen.onMethodName(realToken);break;case Method_Param:this.codeGen.onMethodParameter(realToken);break;case Lambda_New:this.codeGen.genNewLambdaCode(delegateToken.getLambdaFunctionBootstrap());break;case Ternay_End:this.codeGen.onTernaryEnd(realToken);break;}break;default:this.codeGen.onConstant(token);break;}}}

4)调用getResult方法根据生成的字节码构造Expression子类实例(ClassExpression)

  @Overridepublic Expression getResult(final boolean unboxObject) {end(unboxObject);byte[] bytes = this.classWriter.toByteArray();try {Class<?> defineClass =ClassDefiner.defineClass(this.className, Expression.class, bytes, this.classLoader);Constructor<?> constructor =defineClass.getConstructor(AviatorEvaluatorInstance.class, List.class, SymbolTable.class);BaseExpression exp = (BaseExpression) constructor.newInstance(this.instance,new ArrayList<VariableMeta>(this.variables.values()), this.symbolTable);exp.setLambdaBootstraps(this.lambdaBootstraps);exp.setFuncsArgs(this.funcsArgs);exp.setSourceFile(this.sourceFile);return exp;} catch (ExpressionRuntimeException e) {throw e;} catch (Throwable e) {if (e.getCause() instanceof ExpressionRuntimeException) {throw (ExpressionRuntimeException) e.getCause();}throw new CompileExpressionErrorException("define class error", e);}}

2.1.3 if脚本ASM反编译结果

if脚本的asm的解析过程已分析完成,结合上面的if具体脚本示例和源码中asm字节码生成过程,可以得到上述的if脚本示例动态生成的类如下:

1)ifBody生成的lassLambda_1684208818128_57)

public super class Script_11313134242424_59 extends ClassExpression {private final AviatorObject f0=null;private final AviatorJavaType f1=null;private final AviatorFunction f2=null;public void <init> (final AviatorEvaluatorInstance instance, final List<VariableMeta> vars,final SymbolTable symbolTable){super(instance,vars,symbolTable);f0=AviatorLong.valueOf(2);f1=new AviatorJavaType("b", symbolTable);f2=instance.getFunction("__reducer_return",symbolTable);}public final Object execute0(Env env){return RuntimeUtils.assertNotNull(f2.call(env,f1.add(f0, env))).deref(env);}
}

2)elseBody生成的classambda_1684208818128_58)

public super class Script_11313134242424_60 extends ClassExpression {private final AviatorJavaType f0=null;private final AviatorFunction f1=null;public void <init> (final AviatorEvaluatorInstance instance, final List<VariableMeta> vars,final SymbolTable symbolTable){super(instance,vars,symbolTable);f0=new AviatorJavaType("c", symbolTable);f1=instance.getFunction("__reducer_return",symbolTable);}public final Object execute0(Env env){return RuntimeUtils.assertNotNull(f1.call(env,f0)).deref(env);}
}

 3)if语句后面的语句生成的classambda_1684208818128_59)

public super class Script_11313134242424_61 extends ClassExpression {private final AviatorJavaType f0=null;public void <init> (final AviatorEvaluatorInstance instance, final List<VariableMeta> vars,final SymbolTable symbolTable){super(instance,vars,symbolTable);f0=new AviatorJavaType("_reducer_empty", symbolTable);}public final Object execute0(Env env){return f0.deref(env); // return null;}
}

4)整个if脚本生成的class

public super class Script_11313134242424_58 extends ClassExpression {private final AviatorObject f0=null;private final AviatorJavaType f1=null;private final AviatorFunction f2=null;public void <init> (final AviatorEvaluatorInstance instance, final List<VariableMeta> vars,final SymbolTable symbolTable){super(instance,vars,symbolTable);f0=AviatorLong.valueOf(1);f1=new AviatorJavaType("a", symbolTable);f2=AviatorEvaluatorInstance.getFunction("__if_callcc",symbolTable);}public final Object execute0(Env env){RuntimeUtils.assertNotNull(f2.call(env, if(f1.compare(f0, env).booleanValue(env)){RuntimeUtils.assertNotNull(RuntimeUtils.getFunction(this.newLambda(env, "Lambda_1684208818128_57"), env).call(env));}else{RuntimeUtils.assertNotNull(RuntimeUtils.getFunction(this.newLambda(env, "Lambda_1684208818128_58"), env).call(env));},this.newLambda(env, "Lambda_1684208818128_59"))).getValue(env);}
}

2.2 compiledExpression.execute执行过程

上述根据if脚本通过asm字节码最终生成ClassExpression类后,下面即传出变量集env实参进行执行,execute方法如下:

  @Overridepublic Object execute(Map<String, Object> map) {if (map == null) {map = Collections.emptyMap();}Env env = genTopEnv(map);EnvProcessor envProcessor = this.instance.getEnvProcessor();if (envProcessor != null) {envProcessor.beforeExecute(env, this);}try {return executeDirectly(env);} finally {if (envProcessor != null) {envProcessor.afterExecute(env, this);}}}

这里包含了EnvProcessor前置拦截和后置拦截器,下面主要分析下executeDirectly方法具体执行过程:

  @Overridepublic Object executeDirectly(final Map<String, Object> env) {try {Object result = execute0((Env) env);if (RuntimeUtils.isTracedEval(env)) {RuntimeUtils.printlnTrace(env, "Result : " + result);}return result;} catch (ExpressionRuntimeException e) {throw e;} catch (Throwable t) {throw Reflector.sneakyThrow(t);}}

ClassExpression的方法executeDirectly中又调用了execute0进行执行,产出结果,这里的execute0即为上面asm字节码生成部分通过asm生成的成员方法,

针对上述的if脚本示例,生成的ClassExpression子类和实现的execute0方法如下:

public super class Script_11313134242424_58 extends ClassExpression {private final AviatorObject f0=null;private final AviatorJavaType f1=null;private final AviatorFunction f2=null;public void <init> (final AviatorEvaluatorInstance instance, final List<VariableMeta> vars,final SymbolTable symbolTable){super(instance,vars,symbolTable);f0=AviatorLong.valueOf(1);f1=new AviatorJavaType("a", symbolTable);f2=AviatorEvaluatorInstance.getFunction("__if_callcc",symbolTable);}public final Object execute0(Env env){RuntimeUtils.assertNotNull(f2.call(env, if(f1.compare(f0, env).booleanValue(env)){RuntimeUtils.assertNotNull(RuntimeUtils.getFunction(this.newLambda(env, "Lambda_1684208818128_57"), env).call(env));}else{RuntimeUtils.assertNotNull(RuntimeUtils.getFunction(this.newLambda(env, "Lambda_1684208818128_58"), env).call(env));},this.newLambda(env, "Lambda_1684208818128_59"))).getValue(env);}
}

这样,execute0通过传入env实参,执行的方法体即完整实现了if示例脚本的内容,最终产出if脚本计算结果;

其中在执行到某个具体if分支时,会调用newLambda函数:

  public LambdaFunction newLambda(final Env env, final String name) {LambdaFunctionBootstrap bootstrap = this.lambdaBootstraps.get(name);if (bootstrap == null) {throw new ExpressionNotFoundException("Lambda " + name + " not found");}return bootstrap.newInstance(env);}

newLambda函数中会调用缓存的lambdaBootstraps,获取对应的LambdaFunctionBootstrap,然后通过newInstance方法创建对应的LambdaFunction,如下:

  /*** Create a lambda function.** @param env* @return*/public LambdaFunction newInstance(final Env env) {Reference<LambdaFunction> ref = null;if (this.inheritEnv && (ref = this.fnLocal.get()) != null) {LambdaFunction fn = ref.get();if (fn != null) {fn.setContext(env);return fn;} else {this.fnLocal.remove();}}LambdaFunction fn = new LambdaFunction(this.name, this.params, this.expression, env);fn.setInheritEnv(this.inheritEnv);if (this.inheritEnv) {this.fnLocal.set(new SoftReference<>(fn));}return fn;}

后面继续调用LambdaFunction的call函数:

  @Overridepublic AviatorObject call(final Map<String, Object> env) {try {if (this.isVariadic && !this.installed) {return variadicCall(env, true);}return AviatorRuntimeJavaType.valueOf(this.expression.executeDirectly(newEnv(env)));} finally {if (this.inheritEnv) {this.context = null;}}}

call方法体中,又进一步调用了lambda脚本通过asm生成的expression,进而执行了对应分支的逻辑,至此,最终产出计算结果;

3.总结概述

1)LambdaFunctionBootstrap代表的含义

LambdaFunctionBootstrap是对if语法中ifBody,elseBody,elsifBody以及if语句之后的语句构造的模型(也包括其他的while、for、lambda语法等),是对lambda类型脚本通过asm字节码技术编译后的抽象,包含了lambda类型脚本编译后的Expression

2)LRU缓存中缓存的内容

LRU缓存的key为执行脚本本身,String类型

LRU缓存的value为Expression对象,对于ClassExpression子类对象,内部包含了解析的多个LambdaFunctionBootstrap实例,对于上述if脚本示例,即包含3个LambdaFunctionBootstrap实例

3)LambdaFunction代表的含义

在if脚本示例编译后的ClassExpression子类实例中,方法execute0中调用了newLambda方法,在传入参数env后的执行过程中,通过这里的newLambda会创建LambdaFunction对象,LambdaFunction是对lambda类型脚本在执行过程中的抽象,包含了lambda类型脚本编译后的Expression;

在LambdaFunctionBootstrap中实现了对于LambdaFunction(非线程安全)的ThreadLocal线程本地缓存,提交执行效率;

附,LambdaFunction函数作为线程本地缓存,aviator低版本(version<5.3.3)存在内存泄漏问题(JVM内存分析:Aviator低版本内存泄漏问题分析),需要升级到最新的aviator高版本


http://chatgpt.dhexx.cn/article/Zr5r17JB.shtml

相关文章

Aviator使用

“初步了解和使用Aviator” 1.Aviator简介 Aviator 是一个高性能&#xff0c;轻量级的java语言实现的表达式求值引擎&#xff0c;主要用于各种表达式的动态求值。 官方文档 github地址 支持数字、字符串、正则表达式、布尔值、正则表达式等基本类型&#xff0c;完整支持所有…

java aviator_Aviator 表达式求值引擎开源框架

简介 Aviator是一个高性能、轻量级的java语言实现的表达式求值引擎&#xff0c;主要用于各种表达式的动态求值。现在已经有很多开源可用的java表达式求值引擎&#xff0c;为什么还需要Avaitor呢&#xff1f; Aviator的设计目标是轻量级和高性能&#xff0c;相比于Groovy、JRuby…

java aviator_Aviator——让表达式飞起来

《飞行大亨》是我很喜欢的一部电影&#xff0c;不过这里我想介绍的是一个叫Aviator的开源的Java表达式求值器。 一、轮子的必要性 表达式的求值上&#xff0c;java的选择非常多&#xff0c;强大的如Groovy、JRuby&#xff0c;N年没维护的beanshell&#xff0c;包括javaeye上朋友…

Aviator

Aviator 简介 Aviator是一个高性能、轻量级的java语言实现的表达式求值引擎&#xff0c;主要用于各种表达式的动态求值。现在已经有很多开源可用的java表达式求值引擎&#xff0c;为什么还需要Avaitor呢&#xff1f; Aviator的设计目标是轻量级和高性能 &#xff0c;相比于Groo…

Aviator介绍

Aviator简介 Aviator是一个高性能、轻量级的 java 语言实现的表达式求值引擎, 主要用于各种表达式的动态求值。现在已经有很多开源可用的 java 表达式求值引擎,为什么还需要 Avaitor 呢? Aviator的设计目标是轻量级和高性能,相比于Groovy、JRuby的笨重, Aviator非常小, 加上…

西电计算机学院名誉院长,杨孟飞院士受聘为西电计科院名誉院长及讲席教授

西电新闻网讯(通讯员 陈龙)12月21日上午&#xff0c;西安电子科技大学计算机科学与技术学院名誉院长杨孟飞院士“华山学者”讲席教授及战略咨询委员会委员聘任仪式在北校区主楼Ⅱ区319会议室举行&#xff0c;校长杨宗凯、副校长王泉参加仪式。仪式由计科院执行院长崔江涛主持。…

北航计算机学院新闻,澳门理工学院代表团访问我校计算机学院

北航新闻网1月21日电(通讯员 盛浩)2019年1月16日&#xff0c;澳门理工学院副院长李雁莲教授、孙毓奇教授等一行三人到北航计算机学院就双方合作等事项进行交流。 座谈会由先进计算机应用技术教育部工程研究中心熊璋教授主持&#xff0c;计算机学院副院长胡春明副教授、中心李超…

【华人学者风采】陈晓峰 西安电子科技大学

【华人学者风采】陈晓峰&#xff0c;西安电子科技大学网络与信息安全学院副院长。研究方向包括公钥密码学、金融密码学、云计算安全、数据安全、区块链技术及应用、人工智能安全。曾获荣誉&#xff1a; 国家万人计划科技创新领军人才&#xff0c;教育部“青年长江学者” &#…

港科资讯 | 倪明选校长等出席江门“双碳”实验室揭牌暨项目签约仪式

12月7日&#xff0c;由香港科技大学&#xff08;广州&#xff09;&#xff08;筹&#xff09;和江门市政府发起共建的江门“双碳”实验室举行了揭牌暨项目签约仪式&#xff0c;江门双碳实验室正式启动成立。香港科技大学&#xff08;广州&#xff09;&#xff08;筹&#xff09…

莫队算法(普通莫队、带修莫队、树上莫队、不删除莫队)学习笔记【理解+套路/核心代码+例题及题解】

一、理解 我的理解就是巧妙的暴力&#xff0c;利用双指针以及分块思想&#xff0c;巧妙的移动双指针&#xff0c;时间复杂度可以达到O(NlogN)。 强推博客&#xff1a;写的又好又全。链接 二、套路 1、普通莫队 【1】核心代码 bool cmp(node a,node b){return belong[a.l]…

香港理工大学计算机系石杰明老师组招收全奖博士生、博士后

来源&#xff1a;AI求职 香港理工大学 香港理工大学位于中国香港特别行政区&#xff0c;QS 最新排名世界 66 位。计算机系&#xff08;Department of Computing&#xff09;USNews CS 排名 36&#xff0c;泰晤士 CS 排名 79。 石杰明博士课题组成员包括有 985/211 顶尖高校背景…

【调剂】华侨大学计算机学院计算机视觉与模式识别实验室钟必能课题组研究生招生...

点击文末的阅读原文或者公众号界面左下角的调剂信息或者公众号回复“调剂”是计算机/软件等专业的所有调剂信息集合&#xff0c;会一直更新的。 课题组主页&#xff1a;https://cst.hqu.edu.cn/info/1109/2001.htmLinkedin: https://www.linkedin.com/in/bineng-zhong-71a36674…

莫队算法思想

目录 莫队算法普通莫队方法&#xff1a;主要代码结构&#xff1a;例题&#xff1a;小B的询问例题&#xff1a;小Z的袜子奇偶化排序 带修改的莫队小结&#xff1a; 莫队算法 莫队算法是由前国家队莫涛提出的一种算法&#xff0c;主要应用在一类离线区间查询的问题中&#xff0c…

【华人学者风采】冯佳时 新加坡国立大学

【华人学者风采】冯佳时&#xff0c;新加坡国立大学ECE系助理教授。本科毕业于中国科学技术大学&#xff0c;硕士毕业于中国科学院自动化研究所&#xff0c;博士毕业于新加坡国立大学。研究兴趣包括大污染数据分析&#xff0c;在线和分布式鲁棒性学习及其在对象识别中的应用。 …

港科夜闻|央视网专访香港科大(广州)(筹)校长倪明选教授,谈香港科技大学在科研及知识转移方面成就...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、央视网专访香港科大(广州)(筹)校长倪明选教授&#xff0c;谈香港科技大学在科研及知识转移方面成就。香港科技大学(广州)(筹)校长倪明选教授接受央视网专访&#xff0c;谈香港科技大学在科研及知识转移方面取得的成就&am…

独家对话许诗军:数字化转型,最基本的是不去拒绝 |数字价值观察室(下)...

关注ITValue&#xff0c;看企业级最新鲜、最价值报道&#xff01; ▎本文摘自《云栖战略参考》&#xff0c;这本刊物由阿里云与钛媒体联合策划。目的是为了把各个行业先行者的技术探索、业务实践呈现出来&#xff0c;与思考同样问题的“数字先行者”共同探讨、碰撞&#xff0c;…

港科夜闻|香港科技大学(广州)(筹)校长倪明选教授在北京拜访国家教育部党组书记、部长怀进鹏...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科技大学(广州)(筹)校长倪明选教授在北京拜访国家教育部党组书记、部长怀进鹏。2021年11月1日&#xff0c;香港科技大学(广州)(筹)校长倪明选教授等一行在北京拜访国家教育部党组书记、部长怀进鹏。 2、深圳先进院与…

特么的. 最终把 amobbs 的站长阿莫(莫进明)给回骂了一顿.

起因: 假设你居住的地方&#xff0c;要上马PX等高污染的项目&#xff0c;你会怎么做. 鼓动别人上街暴力示威与军警对抗. 自己待在家里支持怂恿. 这样的人真心猥琐! 鉴于他常常私自改动帖子, 在此截图留存. 真特么没劲. 居然以封锁别人 ID 作为别人"打不还手骂不还口…

中国计算机专业创始人,无怨无悔来时路――访计算机专业创始人吴忠明校友

哈工大报讯(研究生记者团杜&#xfffd;/文 李贵才/图)&#xff15;&#xff10;年前&#xff0c;他和他的同事创建了中国最早的计算机专业之一――哈工大计算机专业。从此&#xff0c;“哈工大计算机”作为哈工大的一张名片&#xff0c;&#xff15;&#xff10;载享誉海内外。…

史上首次,45岁计算机大牛蒋濛当选普渡大学校长!

作者丨编辑部 来源丨新智元 【导读】普渡大学史上首位华裔校长诞生&#xff01;45岁计算机大牛蒋濛当选&#xff0c;本硕博全藤校&#xff0c;产学研大满贯的他&#xff0c;此前曾屡拒其他名校。 刚刚&#xff0c;年仅45岁的华裔科学家蒋濛被任命为美国普渡大学第13任校长。 这…