java可用的动态脚本引擎和动态代码执行

2023-10-30

java的ScriptEngine脚本引擎,支持代码动态执行,代码修改后不需要重启JVM进程,就可以使用解析或编译方式执行,非常方便,在动态业务规则、热更新、热修复等场景中会非常方便。
本文介绍3个支持javascript语法和1个支持java语法和脚本引擎。

1、javascript语法引擎

支持运行javascript语法的脚本引擎,主要有三个:

1.1、rhino

官网:https://github.com/mozilla/rhino
Rhino是JavaScript 的一种基于Java的实现,由Mozilla开发,JDK6和JDK7已集成,其它版本JDK需要添加依赖包。
pom.xml

<dependency>
      <groupId>org.mozilla</groupId>
      <artifactId>rhino-engine</artifactId>
      <version>1.7.14</version>
    </dependency>

使用例子

package com.penngo.script;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class RhinoTest {
    public static void main(String[] args) throws Exception{
        String js = """  
                function add (a, b) {
                    var sum = a + b; 
                    // js调用java类
                    java.lang.System.out.println("Script sum=" + sum);
                    return java.lang.Integer.valueOf(sum); 
                }
                """;
        //获得脚本引擎
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine engine = sem.getEngineByName("rhino");
        engine.eval(js);

        Invocable jsInvoke = (Invocable) engine;
        //java中调用js
        Object result = jsInvoke.invokeFunction("add", new Object[] { 13.1, 20.1 });
        System.out.println("Rhino result=" + result);

    }
}

运行结果:

Script sum=33.2
Rhino result=33

1.2、nashorn

官网:https://github.com/openjdk/nashorn
在JDK8-JDK13,Nashorn取代Rhino成为Java的内置集成JavaScript引擎,Nashorn完整支持ECMAScript 5.1的规范以及一些扩展。在JDK8-JDK13外的版本需要添加依赖包:
pom.xml

<dependency>
    <groupId>org.openjdk.nashorn</groupId>
    <artifactId>nashorn-core</artifactId>
    <version>15.4</version>
</dependency>

使用例子

package com.penngo.script;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class NashornTest {
    public static void main(String[] args) throws Exception{

        String js = """
                // js调用java
                var Integer = Java.type("java.lang.Integer");
                var System = Java.type("java.lang.System");
                function add (a, b) {
                    var sum = a + b; 
                    System.out.println("Script sum=" + sum);
                    return Integer.valueOf(sum); 
                }
                """;
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine engine = sem.getEngineByName("nashorn");
        engine.eval(js);
        Invocable jsInvoke = (Invocable) engine;
        //java中调用js
        Object result = jsInvoke.invokeFunction("add", new Object[] { 13.1, 20.1 });
        System.out.println("Nashorn result=" + result);
    }
}

运行结果:

Script sum=33.2
Nashorn result=33

1.3、j2v8

官网:https://github.com/eclipsesource/j2v8
J2V8是一套针对谷歌浏览器chrome的V8 Javascript引擎的java绑定,支持在Android、Windows、Linux、MacOS上运行,需要根据不同平台使用不同时依赖包:

<dependency>
    <groupId>com.eclipsesource.j2v8</groupId>
    <artifactId>j2v8_win32_x86_64</artifactId>
    <version>4.6.0</version>
</dependency>

不同平台的依赖包

  • j2v8_linux_x86_64
  • j2v8_win32_x86_64
  • j2v8_win32_x86
  • j2v8_android_x86
  • j2v8_android_armv7l
  • j2v8_macosx_x86_64

2、Java语法引擎

2.1、Groovy

官网:
http://groovy-lang.org/
https://github.com/groovy
Groovy是在Java虚拟机上实现的动态语言,提供了动态将java代码编译为Java Class对象的功能。需要添加依赖包
pom.xml

<dependency>
  <groupId>org.codehaus.groovy</groupId>
  <artifactId>groovy-all</artifactId>
  <version>3.0.14</version>
  <type>pom</type>
</dependency>

使用例子

package com.penngo.script;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;

public class GroovyTest {
    public static void main(String[] args) throws Exception{
        GroovyClassLoader loader = new GroovyClassLoader();
        // java代码
        String java = """
                public class Test01 {
                    public int add(double a, double b) {
                       double sum = a + b;
                       System.out.println("Script sum=" + sum); 
                       return sum.intValue();
                    }
                  
                }
                """;
        Class scriptClass = loader.parseClass(java);
        GroovyObject scriptInstance = (GroovyObject) scriptClass.getDeclaredConstructor().newInstance();
        Object result = scriptInstance.invokeMethod("add", new Object[]{13.1,20.1});
        System.out.println("Groovy result=" + result);
    }
}

运行结果

Script sum=33.2
Groovy result=33

本文测试源码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java可用的动态脚本引擎和动态代码执行 的相关文章

  • HTML-Entity 转义以防止 XSS

    我有一些用户输入 在我的代码中 我确保对以下符号进行转义 gt amp lt gt lt gt gt gt OWASP https www owasp org index php XSS 28Cross Site Scripting 29
  • JPA:运行时如何指定类对应的表名?

    注意 我对 Java 非常熟悉 但对 Hibernate 或 JPA 还不太熟悉 还没有 我想编写一个通过 JPA 与 DB2 400 数据库通信的应用程序 现在我可以获取表中的所有条目并将它们列出到 System out 使用 MyEcl
  • getAnnotations() 为空

    我想在我的应用程序中使用注释 因此 我为注释创建了 hello world 如下示例 public class HelloAnnotation Foo bar Hello World public String str public sta
  • Android 中的 ImageView 拖动限制

    我在布局中有一个 ImageView 并在 ImageView 上设置 OnTouchListener 来拖动 ImageView 它工作得很好 我的问题是如何防止将 ImageView 移动到布局范围之外 这是我的代码 活动类别 publ
  • Java中的String为什么是不可变的对象,但我在创建一个对象后仍然可以更改它的值? [复制]

    这个问题在这里已经有答案了 如果我可以创建一个字符串并给它一个值 这怎么可能呢 然后 我可以像这样简单地覆盖它的值 String a abc a def 我怎么可能改变的值a 我一定在这里遗漏了一些东西 我知道每当创建 String 对象时
  • 如何使用 apache commons cli 指定多个选项?

    我想要这样的东西 java programName jobs1 C 10 W 20 java programName job2 java programName job3 含内容 Option o1 new Option job2 some
  • Java 中的逻辑回归

    我们需要用 Java 进行逻辑回归 我们在 Python 中使用了这段代码http blog smellthedata com 2009 06 python logistic regression with l2 html http blo
  • java.util.Objects 与Optional 哪个更可取?

    The java util Objects http download java net java jdk9 docs api java util Objects html类通过许多新方法进行了扩展 对象 requireNonNullEls
  • Spring Boot,使用 EhCache 进行缓存

    我需要在我的应用程序中缓存一些数据 我正在考虑使用 Ehcache 我有几个问题 Ehcache需要另外一台服务器吗 我需要其他客户端来使用 Ehcache 吗 Ehcache 如何与多个实例配合使用 是否有可能使用 Ehcache 创建类
  • 如何为我的数独游戏制作 GUI? (摇摆)

    到目前为止 我已经编写了生成随机 9x9 数独网格的代码 我是Java的初学者 所以我有一些关于如何做UI的问题 显示数字的最佳方式是什么 我尝试创建 81 个 JTextFields 这非常乏味 而且我确信有一种有效的方法可以做到这一点
  • 带有 CONTAINS 查询的PreparedStatement

    我有一个查询需要连续运行 28000 次 所以我认为使用准备好的语句可能是一个聪明的主意 这是我的查询 String requestWithFirstName SELECT SE ELEMENT ID SE LASTNAME SE FIRS
  • Cordova Android 应用程序中的网页不可用

    编辑 我一直在解决这个问题并回顾我的所有步骤 我很乐意缩小这个问题的规模 并在令人困惑的情况下获得更多确切的细节 目前 我觉得 Keycloak 似乎只想将我重定向到 https 据我所知 这应该是 Wildfly 服务器配置问题 编辑 我
  • 如何告诉杰克逊在反序列化期间忽略空对象?

    在反序列化过程中 据我理解是将JSON数据转换为Java对象的过程 我如何告诉Jackson 当它读取不包含数据的对象时 应该忽略它 我正在使用 Jackson 2 6 6 和 Spring 4 2 6 我的控制器收到的JSON数据如下 i
  • java POI XSSF 公式评估器

    我在保存新的 Excel 文件时遇到问题 我希望当它被保存时 公式会自行计算 但目前它只是返回 Excel 文件中的一个字符串 公式是正确的 我不知道到底要得到FormulaEvaluator上班 这是我输入返回字符串的公式的地方 data
  • 定时器启动/停止参数

    自从加入这个社区以来 我在技能和进步方面取得了突飞猛进的进步 你们都是一个巨大的帮助 我无法提供一个计时器 该计时器已在启动和停止时实现了某些参数 我要么收到错误消息 局部变量计时器可能尚未初始化 要么没有收到错误消息 但什么也没有发生 也
  • 使用服务器 java api 从 jasperserver 存储库检索资源

    我正在尝试使用其 java API 从 Jasperserver 存储库检索资源 根据jasper 报表服务器终极指南 https community jaspersoft com documentation jasperreports s
  • jstack 是否停止在较新的 JDK8 版本上工作?

    我惊讶地发现 不知何故 最近 jstack 停止了在较新的 JDK 8 上的工作 我不确定这发生在哪个版本 但我确实得到 36649 Unable to open socket file target process not respond
  • 更改 Logger 实例的全局设置

    我在用着java util logging Logger http download oracle com javase 1 4 2 docs api java util logging Logger html作为我的应用程序的日志引擎 每
  • 运行 JAR 时“JCE 无法验证提供者 BC”

    在我的 scala 项目中我使用 org bouncycastle bcprov jdk14 1 51 用于密码学 如果它在 Scala IDE 中测试我的项目 它工作得很好 但是一旦我制作了一个 JAR 并尝试通过以下方式运行它java
  • 如何提高QNX6下Eclipse IDE的性能

    我们在 VMWare 环境中通过 QNX6 运行 Eclipse 速度非常慢 Eclipse 是这样启动的 usr qnx630 host qnx6 x86 usr qde eclipse eclipse data root workspa

随机推荐

  • 【maven】The forked VM terminated without saying properly

    1 概述 转载 https blog csdn net zhglance article details 53695653 一直在使用Maven开发项目 最近遇到了一个让人头疼的问题 在网上搜索竟然没有找到中文描述的解决方式 自己找了英文网
  • linux内核中GPIO的使用(一)--IO内存

    一 相关概念 使用IO内存将物理地址映射为虚拟地址 再通过对虚拟地址的操作来控制硬件 所谓的IO内存是指一种编址方式 不同cpu平台使用的编址方式不同 一种是 IO内存 方式 也叫统一编址方式 是指内存和外设的地址是在同一个地址空间上的 如
  • 手把手教你使用Segformer训练自己的数据

    使用Segformer训练自己的数据 系统配置 代码链接 针对MMCV 选择系统 Windows环境要求 ubuntu 18 04 安装swin segmentation 制作VOC 数据集 代码部分修改 开始训练 使用Transforme
  • mysql实时监控工具mytop

    mysql实时监控工具mytop mytop类似于linux top工具 可以实时监控mysql服务器的性能信息 安装依赖 yum install y perl CPAN cpan cpan gt install DBI cpan gt i
  • vmwaeESXi导出虚拟机和安装

    找到你要导出的虚拟机点击 操作 选择导出 点击 导出 导出的文件会通过浏览器下载到本地 点击创建 注册 选择 从OVF或OVA文件部署虚拟机 点下一页 输入 虚拟机名称 然后点击 单机以选择文件或拖放 以下三个文件就是导出的虚拟机 将三个文
  • docker学习:实战commit

    这里的commit是把你修改后的一个容器打包成一个镜像 这样你本地就多了一个image镜像 有什么用呢 就是你在之前的镜像上的修改连同镜像 成为一个新的image 下次你去布置启动这个修改后的镜像就不用 先下载一个镜像再修改 直接拿你这次c
  • 正则表达式作业

    利用正则表达式完成下面的操作 一 不定项选择题 能够完全匹配字符串 010 62661617 和字符串 01062661617 的正则表达式包括 ABD A r d 3 d 8 B r 0 9 C r 0 9 d D r d d 能够完全匹
  • day049:异常、throws声明异常、throw抛出异常、异常的处理方式

    接下节 day050 try catch 常见问题 throwable的成员方法 自定义异常 ZQyyds 的博客 CSDN博客 一 异常 1 什么是异常 指程序出现了不正常的情况 程序在执行过程中 出现的非正常情况 最终会导致JVM的非正
  • Java课题笔记~JSON

    3 1 概述 概念 JavaScript Object Notation JavaScript 对象表示法 如下是 JavaScript 对象的定义格式 name zhangsan age 23 city 北京 接下来我们再看看 JSON
  • 整理:学术论文发表过程中的审稿人意见答复技巧

    整理 学术论文发表过程中的审稿人意见答复技巧 更新历史 20200613 首次发布 科技论文投稿后 通常都需要答复审稿人的意见 对于审稿人的意见 不能随便敷衍 因为这会让审稿人感到不高兴 说不定转头就把论文拒了 因此 需要按照合适的方式或者
  • rsync linux间同步文件及文件夹

    有时候本地写代码想同步到另一台电脑 又不想push上git 用linux自带的rsync 工具 方便快捷 将本地的salmon目录同步到ray ubuntu电脑上 rsync av salmon ray ray ubuntu home ra
  • 关于服务器环境搭建

    前言 在很多新项目中 都会用到环境搭建的情况 今天教大家如何在服务器中部署应用的环境搭建 一 搭建环境是什么 搭建环境是指建立运行程序文件的基础环境 比如服务运行需要装什么软件都需要哪些程序 服务器的部署就是搭建环境 整理了很久 刚开始搭建
  • C++ 惯用法之 Nifty Counter

    背景 C 中全局对象的初始化在 main 函数执行前完成 在 main 函数执行结束前销毁 在同一源码文件中全局变量的初始化顺序和其定义顺序一致 但在不同的源码文件中其初始化顺序不一致 就有可能导致代码出错 一般解决方法 概述 静态局部变量
  • 计算机图形学-扫描转换直线段-直线方程法-DDA算法-中点算法-OPENGL实现-详解

    扫描转换直线段 说明与环境配置 环境配置 扫描转换直线段 方法一 直线方程法 代码描述 算法比较简单 暂无代码 方法二 数字差分分析DDA算法 代码描述 方法三 中点算法 代码描述 所有代码下载与效果展示 说明与环境配置 生成一个线段的方法
  • pthread_mutex_trylock使用

    pthread mutex trylock 是 pthread mutex lock 的非阻塞版本 如果被其他线程使用 返回其他值 如果没有被其他线程使用 那么进行加锁 并且返回0 所以可以通过这个判断是不是使用这这个锁 而不需要等待 提高
  • Django生成唯一流程单号

    class AutoSerialNumber object 创建OA单号 def init self J201906120001 self fd apply no ApplicationBasicFormModel delete objec
  • 网络基础IP地址

    IP地址 IP地址分类 子网划分 VLSM 超网 路由聚合 CIDR IP地址分类 A类 0开始 B类 27 128 开始 C类 27 26 192 开始 D类 27 26 25 224开始 E类 27 26 25 24 240开始 特殊I
  • 从Map中 取出第一个key/第一个value的方法

    从Map中取出第一个 key 和 value 的方法 使用Map Entry进行操作 可与LinckedHashMap 按元素存入顺序排序的有序Hash表 搭配使用 实现特定的业务要求 获取map中第一个key值 param map 数据源
  • Qemu-KVM安装

    目录 前提准备 1 虚拟机需要GNOME界面 如果是字符界面需要下载安装GNOME界面 2 安装vncviewer 3 安装xshell SecureCRT xftp WinSCP 或finalshell 一 Qemu KVM虚拟化环境搭建
  • java可用的动态脚本引擎和动态代码执行

    文章目录 1 javascript语法引擎 1 1 rhino 1 2 nashorn 1 3 j2v8 2 Java语法引擎 2 1 Groovy java的ScriptEngine脚本引擎 支持代码动态执行 代码修改后不需要重启JVM进