JDK1.8 nashorn 引擎使用

简介: 整理了近期在项目上做的一些技术研究,希望与大家共同探讨交流。 在清算项目的计算模块使用 jdk 1.8 自带的 js 引擎 nashorn 做运算。 使用过程对 nashorn 做了一些简单的测试。

整理了近期在项目上做的一些技术研究,希望与大家共同探讨交流。

在清算项目的计算模块使用 jdk 1.8 自带的 js 引擎 nashorn 做运算。 使用过程对 nashorn 做了一些简单的测试。

使用 nashorn 编译 js 后 执行 invokeFunction 计算 ,一个简单的逻辑判断 加上一个简单的乘法运算 循环执行100w次总耗时约为600~700ms

使用 mozilla 的 rhino js引擎, 编译 js 后 执行 func.call 计算 ,总耗时约为 1400ms 左右。

nashorn 中 eval 方法编译 js 耗时很大, 实际应用时需要进行缓存处理。

除此之外, 使用 nashorn 过程一直调用不到内部的 js 方法。

这里记录下这次的使用方式

public class LiquidationUtil {
    private static Logger logger = LoggerFactory.getLogger(LiquidationUtil.class);
     
    public static final String _expression = "_expression";
    public static final String _conditions = "_conditions";
    // 生成清算规则的计算对象
    public static Invocable  generateLiquidationFuction(String conditions,String expressionMark,String expressionParam) throws ScriptException, NoSuchMethodException {//Liquidation
        StringBuffer sb = new StringBuffer(128);
        if(StringUtils.isEmpty(conditions))
            conditions = "true";
         
        sb.append("var ").append(_conditions).append(" = function (m,o) {")
            .append("\nreturn ").append(_conditions).append("(m,o,null);\n")
        .append("};\n");
        sb.append("var ").append(_expression).append(" = function (m,o) {")
            .append("\nreturn ").append(_expression).append("(m,o,null);\n")
        .append("};\n");
         
        // 条件
        sb.append("var ").append(_conditions).append(" = function (m,o,jh) {")
            .append("\nreturn ").append(conditions).append(";\n")
        .append("};\n");
         
         
        String expressionJs = expressionMap.get(expressionMark);
        // 计算
        sb.append("var ").append(_expression).append(" = function (m,o,jh) {")
            .append("\nvar result=null;\n")
            .append("\n var ").append(expressionParam).append(";\n")
            .append("\n").append(expressionJs).append(";\n")
            .append("\nreturn result;\n")
        .append("};");
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");//nashorn javascript
        engine.eval(sb.toString());
        return (Invocable) engine;
    }
     
     
     
     
    private static final Map<String, String> expressionMap = new HashMap<String, String>();
    static {
        try {
            String path = Thread.currentThread().getContextClassLoader().getResource("liquidation_script").getFile();
            logger.info("加载清算规则js脚本 path:{}", path);
            File dir = new File(path);
            for(File script : dir.listFiles()) {
                String fileName = script.getName();
                String filePath = script.getAbsolutePath();
                logger.info("加载清算规则脚本 mark:{}\tfilePath:{}",fileName, filePath);
                expressionMap.put(fileName.substring(0, fileName.length()-3), readFileContent(filePath));
            }
        } catch (IOException e) {
            logger.error("初始化算费规则脚本出错", e);
        }
    }
    public static String readFileContent(String uri) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(uri));
        String line = "";
        StringBuffer buffer = new StringBuffer();
        while ((line = br.readLine()) != null) {
            buffer.append(line).append("\n");
        }
        String fileContent = buffer.toString();
        return fileContent;
    }
}
调用:
            jsInvocable = (Invocable)LiquidationUtil.generateLiquidationFuction(conditionsJs, expressionMark, expressionParam);// 对 invocable 缓存
            result = jsInvocable.invokeFunction(_conditions, mapping, orderInfo);

js 代码的格式为

var func1 = function(param1, param2){

...

}

var func2 = function(param1, param2){

...

}

对这段字符串执行 eval, 得到 Invocable ,

然后可以执行 Invocable.invokeFunction("func1", param1, param2) 调用 js 方法。

目录
相关文章
|
JavaScript 前端开发 Oracle
JDK10特性
2018年3月21日,Oracle官方宣布JAVA10正式发布。 JAVA9和JAVA10都不是 LTS (Long-Term-Support)版本,和过去的JAVA大版本升级不同,这两个只有半年左右的开发和维护时间。
65 0
|
Oracle 安全 Java
JDK11特性
2018年9月26日,Oracle官方发布JAVA11。这是JAVA大版本周期变化后的第一个长期支持版本,非常值得关注。
139 0
|
SQL 前端开发 Java
大数据平台底层技术-JAVA篇-如何动态加载不同版本的 HIVE JDBC 驱动 - 一文读懂JAVA的类加载机制 1
大数据平台底层技术-JAVA篇-如何动态加载不同版本的 HIVE JDBC 驱动 - 一文读懂JAVA的类加载机制
|
8月前
|
网络协议 JavaScript 前端开发
Java一分钟之-GraalVM Native Image:构建原生可执行文件
【6月更文挑战第13天】GraalVM Native Image是Java开发的创新技术,它将应用编译成独立的原生可执行文件,实现快速启动和低内存消耗,对微服务、桌面应用和嵌入式系统有重大影响。本文讨论了如何使用Native Image,包括常见挑战如反射与动态类加载、静态初始化问题和依赖冲突,并提供了解决方案和代码示例。通过合理规划和利用GraalVM工具,开发者可以克服这些问题,充分利用Native Image提升应用性能。
377 5
|
7月前
|
Java 关系型数据库 MySQL
GraalVM 静态编译下 OTel Java Agent 的自动增强方案与实现
在 2024 OpenTelemetry Community Day 会议中,阿里云可观测工程师张乎兴(望陶)和饶子昊(铖朴)为大家带来了《GraalVM 静态编译下 OTel Java Agent 的自动增强方案与实现》的演讲分享,介绍阿里云在相关领域的探索方案,本文是相关分享对应的中文整理。
295 20
|
8月前
|
安全 Oracle Java
Java一分钟之-GraalVM:高性能运行时与编译器
【6月更文挑战第12天】GraalVM是Oracle实验室的高性能运行时和编译器,支持Java、JavaScript等多语言,提供即时编译和提前编译技术,提升应用性能和跨语言互操作性。其核心亮点包括多语言支持、高性能、Native Image(AOT编译)和安全沙箱。常见问题涉及Native Image构建失败、反射与动态加载处理及资源消耗误解。解决这些问题需要详细阅读官方文档、利用GraalVM工具链和参考社区资源。通过Native Image,开发者可以构建接近零启动时间的原生应用。GraalVM是打破语言壁垒、提升应用效率的有力工具,随着生态发展,将在技术领域发挥更大作用。
225 1
|
SQL Java 大数据
大数据平台底层技术-JAVA篇-如何动态加载不同版本的 HIVE JDBC 驱动 - 一文读懂JAVA的类加载机制 2
大数据平台底层技术-JAVA篇-如何动态加载不同版本的 HIVE JDBC 驱动 - 一文读懂JAVA的类加载机制
|
9月前
|
Java 测试技术
AtomicReference新jdk特性
AtomicReference新jdk特性
54 0
JDK各个版本的特性分析|JDK7|JDK8|JDK9|JDK10|JDK11|JDK12|JDK13特性分析
JDK各个版本的特性分析|JDK7|JDK8|JDK9|JDK10|JDK11|JDK12|JDK13特性分析
|
Java 编译器 开发工具
JAVA工具-JDK、JRE、JVM、JIT
JAVA工具-JDK、JRE、JVM、JIT
194 0