killme2008 / killme2008/aviatorscript
将表达式编译后的字节流结果存入redis,然后反序列化报错
- Dominant language
- Java
- Stars
- 5.2k
- Forks
- 906
- PR merge metrics
- No merged PRs in 30d
Description
使用如下工具类 AviatorUtilsDemo将表达式编译后的字节流(bytes[])结果存入redis,然后取出反序列化报错
deserializeExpression方法报错:
`2024-08-22 17:00:02.770 [http-nio-8083-exec-2] ERROR com.xxx.RestExceptionHandler:23 - org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.LinkageError: loader (instance of com/googlecode/aviator/parser/AviatorClassLoader): attempted duplicate class definition for name: "AviatorScript_1724315357698_58"`
序列化和反序列化代码
```java
@Slf4j
public class AviatorUtilsDemo {
/**
* 初始化执行引擎
*/
private static final AviatorEvaluatorInstance engine;
static {
engine = AviatorEvaluator.getInstance();
engine.setOption(Options.SERIALIZABLE, true);
}
/**
* execute the expression
* @param expression
* @param paramMap
* @param resultType
* @return
*/
public static T executeExpression(Expression expression, Map paramMap, Class resultType) {
return resultType.cast(expression.execute(paramMap));
}
/**
* execute the expression
* @param bs
* @param paramMap
* @param resultType
* @return
*/
public static T executeExpression(byte[] bs, Map paramMap, Class resultType) {
Expression expression = deserializeExpression(bs);
return resultType.cast(expression.execute(paramMap));
}
/**
* execute the expression
* @param expression
* @param resultType
* @return
*/
public static T executeExpression(Expression expression, Class resultType) {
return resultType.cast(expression.execute());
}
/**
* execute the expression
* @param bs
* @param resultType
* @return
*/
public static T executeExpression(byte[] bs, Class resultType) {
Expression expression = deserializeExpression(bs);
return resultType.cast(expression.execute());
}
/**
* execute the expression
* 谨慎使用 会导致metaspace OOM
* @param expressionStr
* @param paramMap
* @param resultType
* @return
*/
public static T executeExpression(String expressionStr, Map paramMap, Class resultType) {
Expression expression = engine.compile(expressionStr);
return resultType.cast(expression.execute(paramMap));
}
/**
* execute the expression
* 谨慎使用 会导致metaspace OOM
* @param expressionStr
* @param resultType
* @return
*/
public static T executeExpression(String expressionStr, Class resultType) {
Expression expression = engine.compile(expressionStr);
return resultType.cast(expression.execute());
}
/**
* Serialize the expression
* @param expression
* @return
*/
public static byte[] serializeExpression(String expression) {
byte[] bs = null; // the serialized bytes
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
// Create the ObjectOutputStream
ObjectOutputStream output = engine.newObjectOutputStream(out);
// Write the expression object
output.writeObject(engine.compile(expression));
output.close();
// Get the result byte array
bs = out.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e);
}
return bs;
}
/**
* Deserialize expression from bytes
* @param bs
* @return
*/
public static Expression deserializeExpression(byte[] bs) {
Expression expression = null;
try (ByteArrayInputStream in = new ByteArrayInputStream(bs)) {
// Create the ObjectInputStream from ByteArrayInputStream(bs)
ObjectInputStream input = engine.newObjectInputStream(in);
// Read the expression from ObjectInputStream
expression = (Expression) input.readObject();
} catch (Exception e) {
log.error("avaitor deserializeExpression err", e);
// throw new RuntimeException(e);
}
return expression;
}
public static void main(String[] args) {
// Boolean b = AviatorUtils.executeExpression("1+1==3", Boolean.class);
// System.out.println(b);
//
// Map map = new HashMap<>();
// map.put("price", 20);
// Boolean b1 = AviatorUtils.executeExpression("price>30", map, Boolean.class);
// System.out.println(b1);
Map map = new HashMap<>();
map.put("price", 30);
map.put("period", "14d");
byte[] bs = AviatorUtilsDemo.serializeExpression("(price>=29.99)&&(period=='14d')");
Boolean b2 = AviatorUtilsDemo.executeExpression(bs, map, Boolean.class);
System.out.println(b2);
}
}
```
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the AviatorUtilsDemo serializeExpression and deserializeExpression entry points, especially the shared engine setup and the ObjectInputStream/ObjectOutputStream calls. Reproduce the Redis round trip using the expression and parameters in the example, then inspect the deserialization path; done means the serialized expression can be read and executed without the duplicate AviatorScript class-definition error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, redis
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100