Backend Development 9 min read

Mastering Aviator: A High‑Performance Java Expression Engine for Backend Development

Aviator is a lightweight, high‑performance Java expression evaluation engine that compiles expressions to JVM bytecode, offering rich operator support, custom functions, variable handling, and compilation for reuse, while detailing its features, limitations, dependency setup, and multiple code examples for practical backend integration.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Aviator: A High‑Performance Java Expression Engine for Backend Development

Aviator Introduction

Aviator is a high‑performance, lightweight Java expression evaluation engine designed for dynamic evaluation of various expressions. Compared with heavyweight scripting languages like Groovy or JRuby, Aviator is small (≈450 KB with dependencies, ≈70 KB without) and its syntax is a limited subset of a full language.

Unlike many evaluators that interpret expressions, Aviator compiles them directly to Java bytecode, positioning it between heavyweight script languages and ultra‑lightweight engines.

Aviator Features

Supports most operators: arithmetic, relational, logical, bitwise, regex (=~), ternary (?:) with proper precedence and parentheses.

Function calls and custom functions.

Built‑in regex matching with Ruby/Perl‑style syntax and $digit group references.

Automatic type conversion; operations convert operands as needed, throwing an exception if conversion fails.

Variable injection with nested access (e.g., a.b.c).

Functional‑style

seq

library for collections and arrays.

Aviator Limitations

No control‑flow statements such as

if

,

else

,

do/while

; only logical, arithmetic, ternary, and regex expressions are allowed.

Octal literals are not supported; only decimal and hexadecimal literals are allowed.

Overall Structure

Aviator’s architecture is simple, following the typical evaluator design.

Usage Examples

Dependencies

<code><dependency>
  <groupId>com.googlecode.aviator</groupId>
  <artifactId>aviator</artifactId>
  <version>5.2.5</version>
</dependency>
<dependency>
  <groupId>commons-beanutils</groupId>
  <artifactId>commons-beanutils</artifactId>
  <version>1.9.4</version>
</dependency>
<dependency>
  <groupId>commons-logging</groupId>
  <artifactId>commons-logging</artifactId>
  <version>1.2</version>
</dependency>
</code>

Example 1: Simple addition

<code>public class SimpleExample {
  public static void main(String[] args) {
    Long result = (Long) AviatorEvaluator.execute("1+2+3");
    System.out.println(result);
  }
}
</code>

The result is a

Long

, because Aviator only supports

Long

and

Double

numeric types.

Example 2: Passing parameters

<code>public class InputParamsExample {
  public static void main(String[] args) {
    Map<String, Object> env = new HashMap<>();
    env.put("name", "张三");
    String result = (String) AviatorEvaluator.execute("'你的姓名是' + name", env);
    System.out.println(result);
  }
}
</code>

Output: 你的姓名是张三。

Example 3: exec method (Aviator 2.2+)

<code>public class ExecParamsExample {
  public static void main(String[] args) {
    String myname = "dennis";
    Object result = AviatorEvaluator.exec("'hello ' + name", myname);
    System.out.println(result);
  }
}
</code>

Example 4: Function calls (Lua‑like syntax)

<code>public class InvokeFunctionExample {
  public static void main(String[] args) {
    Object res1 = AviatorEvaluator.execute("string.length('hello')");
    Object res2 = AviatorEvaluator.execute("string.substring('hello',1,2)");
    Object res3 = AviatorEvaluator.execute("string.contains('hello','ll')");
    Object res4 = AviatorEvaluator.exec("string.length(name)", "我是中国人");
    System.out.println(res1 + "\t" + res2 + "\t" + res3 + "\t" + res4);
  }
}
</code>

Example 5: Custom function

Implement

com.googlecode.aviator.runtime.type.AviatorFunction

(or extend

AbstractFunction

) and register it.

<code>public class AddFunction extends AbstractFunction {
  @Override
  public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
    Number left = FunctionUtils.getNumberValue(arg1, env);
    Number right = FunctionUtils.getNumberValue(arg2, env);
    return new AviatorDouble(left.doubleValue() + right.doubleValue());
  }
  public String getName() {
    return "add";
  }
}
</code>
<code>public class CustomFunctionExample {
  public static void main(String[] args) {
    AviatorEvaluator.addFunction(new AddFunction());
    System.out.println(AviatorEvaluator.execute("add(10,100)"));
  }
}
</code>

Example 6: Compile expression

<code>public class CompileExample {
  public static void main(String[] args) {
    String expression = "a-(b-c) > 100";
    Expression compiledExp = AviatorEvaluator.compile(expression);
    Map<String, Object> env = new HashMap<>();
    env.put("a", 100.3d);
    env.put("b", 45);
    env.put("c", -199.100d);
    Boolean result = (Boolean) compiledExp.execute(env);
    System.out.println(result);
  }
}
</code>

Compiled expressions can be reused with different environments, improving performance. The engine supports comparison operators for numbers, strings, patterns, booleans, and any objects implementing

java.lang.Comparable

.

Example 7: Access arrays and collections

<code>public class CollectionExample {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("我是");
    list.add("中国人");
    int[] array = new int[3];
    array[0] = 10;
    array[1] = 100;
    array[2] = 1000;
    Map<String, Object> map = new HashMap<>();
    map.put("date", LocalDate.now());
    Map<String, Object> env = new HashMap<>();
    env.put("list", list);
    env.put("array", array);
    env.put("mmap", map);
    System.out.println(AviatorEvaluator.execute(
        "list[0]+list[1]+'\narray[0]+array[1]+array[2]='+ (array[0]+array[1]+array[2]) +' \ntoday is '+ mmap.date",
        env));
  }
}
</code>

The next article will cover ternary operators, regex matching, date comparison, big‑number calculations, and precision.

JavaperformanceBackend Developmentaviatorexpression-engineCode SamplesCustom Functions
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.