Java环境与Android环境中使用QuickJS

至简网格的服务器主体是用Java实现的,业务接口绝大部分用json文档即可实现,较为复杂的逻辑用到JS。JS引擎,用V8显得太重,选择graaljs就对java运行环境产生依赖,并且安卓不支持,所以最终选择QuickJS,功能、性能都满足要求。

开源的java封装中,大多都几年没更新了,找了一个更新比较近的开源项目(HarLongWang QuickJS Wrapper),继承了它的功能,并做了以下改进:

  1. 将QuickJS替换为QuickJS-NG(有改进,由社区维护,不依赖单个大牛);
  2. 改正了一些小bug.
  3. 实现ESModule支持(用法见项目开源首页);
  4. 增加NativeLibraryLoader,模仿xerial sqlite jdbc驱动的实现;
  5. 增加Logger支持,默认的console实现使用Logger输出;
  6. 支持Linux、Windows、Termux、Android(只支持64位芯片架构);
  7. 增加测试用例。

开源地址(APL协议,jar、aar文件在开源库的release中,没有放maven):ZhiJianMesh/QuickJS: QuickJS java wrapper modified based on harlonwang's QuickJS

QuickJS: QuickJS java wrapper modified based on harlonwang's QuickJS

为什么不直接使用HarLongWang QuickJS?因为这个项目只提供了安卓的原生库,没有提供jvm中的原生库。反正都需要自己搭建环境编译,并且我还需要在Termux中运行(使用Android的so是不行的),所以干脆自己搞一个,顺便做一点改进。

使用很简单,最基本的使用方法如下:

java 复制代码
    QuickJSContext context = QuickJSContext.create();
    // evaluating JavaScript
    context.evaluate("1 + 2;"); //3
    // destroy QuickJSContext
    context.close();

Js使用Java中的对象:

java 复制代码
    public class FunctionCls {
        private int base = 0;
        public FunctionCls() {}
        public FunctionCls(int base) {this.base = base;} 
        
        //添加注解,会自动绑定到js对象中
        @JavascriptMethod
        public int add(int a, int b) {
            return a + b + base;
        }
    }
    

    //context.setLogger(QuickJSContext.SystemConsole);
    JSObject global = context.getGlobalObject();
        
    global.setProperty("funcCls", FunctionCls.class);
    Object result = context.evaluate("funcCls.add(1,99)"); //100
        
    FunctionCls base = new FunctionCls(10);
    global.setJavaObject("funcCls1", base);
    result = context.evaluate("funcCls1.add(1,99)"); //110

Java使用Js中的函数:

java 复制代码
    context.evaluate("function test_aaa(a) {return 'aaa_'+a;}");
    JSFunction jf = context.getGlobalObject().getJSFunction("test_aaa");
    Object r = jf.call("test"); //aaa_test
    jf.release(); //如非必要,JSObject最好及时释放

使用模块,除了下面这种使用方法,还有其他使用方式,请参照项目首页介绍:

java 复制代码
    Object o = getContext().evaluateModule(
            "export var name = 'Jack';\n" +
            "export var age = 18;\n" +
            "export function report() { return name + ':' + age};", 
            "a.js");

    JSObject module = (JSObject) o;
    String name = module.getProperty("name"); //Jack
    int age = (Number)module.getProperty("age")).intValue(); //18
    JSFunction f = module.getJSFunction("report");
    String result = (String) f.call(); // Jack:18
    f.release();
    module.release();

更多例子请参照开源库首页的ReadMe,或者参照Junit的测试用例。

如果项目对你有用,在项目首页给个star以示鼓励,谢谢!

相关推荐
Lhappy嘻嘻10 小时前
Java IO|File 文件操作 + 字节流 / 字符流完整笔记 + 递归删除文件实战
java·笔记·php
胡萝卜术11 小时前
从API调用到手写LRU:力扣146「LRU缓存」的哈希表+双向链表终极进化之路
前端·javascript·面试
科技道人11 小时前
记录 默认置灰/禁用 app ‘Search Engine Selector‘ 的disable按钮
开发语言·前端·javascript
伊玛目的门徒11 小时前
试用leetcode之典中典 二数之和问题
java·算法·leetcode
逝水无殇13 小时前
C# 异常处理详解
开发语言·后端·c#
懒鸟一枚14 小时前
深入理解 Linux 内存、Swap 交换分区与分页机制的关系
java·linux·数据库
玖玥拾14 小时前
C# 语言进阶(十五)C# 游戏服务端 MySQL 数据库
服务器·开发语言·网络·数据库·mysql·c#
铅笔侠_小龙虾15 小时前
Rust 学习目录
开发语言·学习·rust
我命由我1234515 小时前
执行 Gradle 指令报错,无法将“grep”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
考虑考虑15 小时前
Sentinel安装
java·后端·微服务