当前位置: 首页 > news >正文

字体图标制作网站建设证书查询官方网站

字体图标制作网站,建设证书查询官方网站,免费网站建设大全,游戏开发需要多少钱?这是2024年初的 GraalVM 系列博文,当时写了大纲,知道一年半后的现在才得以完成发布😄 1、概述 实话说,标题的场景为小众需求,日常开发基本用不到,我是最近在做一个低代码轮子玩具 app-meta 需要实现 FaaS&…

这是2024年初的 GraalVM 系列博文,当时写了大纲,知道一年半后的现在才得以完成发布😄

1、概述

实话说,标题的场景为小众需求,日常开发基本用不到,我是最近在做一个低代码轮子玩具 app-meta 需要实现 FaaS(Function as a Service)功能才接触到 JS 引擎。还有如下的场景会用的上:

  • 调用 js 特有的函数(java 体系没有更好的选择)
  • 动态执行代码(代码逻辑随时可修改,这一块脚本语言有天然优势)
  • 需要利用脚本语言扩展 Java 功能

我计划针对在JVM跑JavaScript脚本写系列的文章:

  1. 在JVM跑JavaScript脚本 | Oracle GraalJS 简介与实践
  2. 在JVM跑JavaScript脚本 | FaaS架构简单实现

温馨提示:文章内容较长,可按需定位章节阅读😃

1.1、JVM 下 JS 引擎

内置引擎

引擎所属 JDK 版本基于的 ECMAScript 版本备注
RhinoJDK 6 及之前(Java 1.6)ES3(部分 ES5)由 Mozilla 用 Java 编写,最早的 JVM JS 引擎,速度慢但易集成。
NashornJDK 8 ~ JDK 14ES5.1(少量 ES6 特性)Oracle 开发,性能较 Rhino 高,支持 Java <-> JS 互操作;JDK 15 开始移除。

外部高性能引擎

引擎运行机制特点项目链接
Graal.jsGraalVM 提供的 JS 实现支持 ES2022 及后续,性能高,可与 Java 混合调用,无需 JNI 手写Graal.js 官方
JavetJNI 调用 V8 引擎完整支持现代 JS/Node API,性能接近 Node.jsJavet
Duktape-Java嵌入 Duktape 引擎小巧、易嵌入、启动快,适合轻量脚本执行Duktape-Java
QuickJS-JavaJNI 调用 QuickJS支持最新 JS 特性(ES2020+),内存占用小QuickJS-Java

再后来,GraalVM 横空出世,它是 Oracle Labs 开发的一款 高性能、多语言虚拟机,目标是在 同一个运行时 下高效运行多种编程语言(Java、JavaScript、Python、Ruby、R、LLVM-based 语言、WebAssembly 等),并且实现这些语言之间的无缝互操作。

主要组件

组件作用
Graal Compiler高性能 JIT 编译器,可替代 HotSpot 的 C2 编译器。
GraalJS在 GraalVM 上运行的 JavaScript/Node.js 实现,支持现代 ECMAScript 规范。
Truffle一套多语言实现框架,用于开发新语言运行时。
Native ImageAOT 编译工具,将 Java 应用打包成本地二进制可执行文件。
Polyglot API提供跨语言调用的统一 API。

今天我们的主角就是 GraalJS。

1.2、 GraalJS 简介

GraalJS: A ECMAScript 2022 compliant JavaScript implementation built on GraalVM. With polyglot language interoperability support. Running Node.js applications!

翻译过来就是,GraalJS 是基于 GraalVM 构建,兼容 ECMAScript 2022 语法的 JavaScript 实现,能够运行 Node.js 应用,同时支持 polyglot (多语言互操作)。

为什么选择它?

最主要原因是它支持较新的 js 语法,有大公司背书,还考虑到 GraalVM 还支持其他脚本语言(如 python),有利于以后的功能扩展。


2、开始使用

📦 依赖引入

此处以 maven 为例

<!-- 增加 GraalJS 依赖,graalvm.version 替换为最新的版本号即可 -->
<properties><graal.version>24.2.1</graal.version>
</properties><dependencies><dependency><groupId>org.graalvm.polyglot</groupId><artifactId>polyglot</artifactId><version>${graal.version}</version></dependency><dependency><groupId>org.graalvm.polyglot</groupId><artifactId>js</artifactId><version>${graal.version}</version><type>pom</type></dependency>
</dependencies>

👋 惯例 Hello World

import org.graalvm.polyglot.Context;public class GraalJSDemo {public static void main(String[] args) {try (Context context = Context.create()) {context.eval("js", "console.log(`来自 GraalJS 的问候!Time=${Date.now()}`)");}}
}

代码浅析

  • ContextGraalVM Polyglot API 的核心类。它代表一个“多语言执行上下文”(Execution Context),里面可以执行不同语言的代码,比如 "js"(JavaScript)、"python""ruby" 等。

  • 每个 Context 可以看成是一个沙箱(sandbox),里面有独立的全局变量、函数等运行环境。

  • 使用 try-with-resources,保证 Context 在使用结束后会自动关闭并释放资源(例如内存、线程等)。

  • Context.create() 会创建一个默认的多语言上下文:

    • 默认启用 JavaScript、Python 等 GraalVM 已安装的语言(如果你是 GraalVM Standard Edition,可能默认只开启 JavaScript)。
    • 你也可以用 Context.create("js") 来只创建 JS 运行环境(更精简)。
  • eval(languageId, sourceCode) 用来在指定语言中执行一段代码。

    • languageId"js" 代表执行 JavaScript 代码。
    • sourceCode"console.log('Hello from GraalJS!')" 是要运行的 JavaScript 源码。
  • 在 GraalVM 里,console.log 是 Graal.js 提供的一个 JS 全局函数,输出到 Java 的标准输出(System.out)。

执行后,你会在 Java 控制台看到:

💱 参数传递

我们可以在 JavaScript 里定义函数,然后从 Java 调用它,传递参数。这种方式适合当脚本是函数而不是全局执行代码

/*** 构建一个 JS 函数,支持传递参数并得到结果*/
@Test
public void funWithParams(){try(Context ctx = Context.create(JS)){// 构建函数对象Value addFunc = ctx.eval(JS, "(x, y)=> x+y");// 传递参数调用它int result = addFunc.execute(100, 100).asInt();System.out.println("执行 100+100 函数,结果="+result);}
}

🔌 全局变量

全局变量就是给 JS 引擎赋予全局可访问的值,类似于 HTML 中的 window😄。这里就需要用到Bindings组件。GraalVM 的 Bindings 类似于一个共享的变量表,你可以在 Java 里放值,JS 直接读取。同时参数类型也会自动映射(Java 数字 → JS 数字)👍。

定义 Java 类

public class JavaLogger {// 定义时间格式器(HH表示24小时制,hh表示12小时制)DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");private void log(String level, String msg){String time = LocalTime.now().format(formatter);System.out.printf("[JAVA] %s %-5s %s%n", time, level, msg);}public void info(String msg){ log("INFO", msg); }public void debug(String msg){ log("DEBUG", msg); }public void error(String msg){ log("ERROR", msg); }
}
private void printValue(Value value){System.out.printf("%n------------------------ 脚本返回值 ------------------------%n%s", value);
}/*** 设置全局变量*/
@Test
public void bindings(){/*** 自定义 Java 、JS 互通规则,按需开启对应的权限-*/HostAccess hostAccess = HostAccess.newBuilder()//允许不受限制地访问所有公共构造函数、公共类的方法或字段.allowPublicAccess(true)//允许客户端语言实现任何 Java 接口.allowAllImplementations(false)//允许客户端语言实现(扩展)任何 Java 类.allowAllClassImplementations(false)//允许访问数组.allowArrayAccess(false)//允许访问 List.allowListAccess(false)//允许客户应用程序以缓冲区元素的形式访问 ByteBuffers.allowBufferAccess(false)//允许客户应用程序使用迭代器将可迭代对象作为值进行访问.allowIterableAccess(false)//允许客户应用程序将迭代器作为迭代器值进行访问。.allowIteratorAccess(false)//允许客户应用程序以哈希值形式访问 Map 对象.allowMapAccess(true)//允许客户应用程序继承对允许方法的访问权限.allowAccessInheritance(false).build();// 使用自定义 HostAccess 构建 Contexttry(Context ctx=Context.newBuilder(JS).allowHostAccess(hostAccess).build()){Value global =  ctx.getBindings(JS);global.putMember("UUID", UUID.randomUUID().toString());// 传递 Map 键值对global.putMember("User",Map.of("name", "集成显卡","url", "https://github.com/0604hx"));// 放置对象示例global.putMember("log", new JavaLogger());String script = """log.info(`开始执行 JS 脚本,UUID=${UUID}`)log.debug(`测试 debug 日志...`)log.error(`测试 error 日志...`)let result = { time: Date.now(), name: User.name, uuid: UUID }result""";printValue(ctx.eval(JS, script));}
}


关于 HostAccess 权限,可以查看官方文档:HostAccess.Builder。

⛑️ 安全管理

allowAllAccess

Context.allowAllAccess 是 GraalVM Polyglot API 里 Context.newBuilder() 的一个配置,用来放开 Java 与其他语言之间的所有访问限制。

如果通过context.allowAllAccess(true),则表示:“我信任这个脚本,允许它干任何事,包括直接操作 Java 类、方法、字段,甚至文件系统和网络”。对于不明来源不明作用的脚本,这是非常危险的!所以,该项是默认 false。除非特殊情况,我都强烈建议关闭它。在脚本真要调用什么 Java 代码,可以通过全局对象来实现。

开启 allowAllAccess(true) 后:

  • 解除几乎所有安全限制
  • JS / Python / 其他脚本语言可以直接调用 Java API
  • 可以访问文件、网络、系统属性等

例子(JS 调用 Java 类):

try (Context context = Context.newBuilder("js").allowAllAccess(true).build()) {context.eval("js", """const File = Java.type('java.io.File');let f = new File('test.txt');console.log("Absolute Path:", f.getAbsolutePath());""");
}

如果没有 allowAllAccess(true),上面会抛异常:

java.lang.SecurityException: Access to host classes is not allowed.

allowIO

默认情况下, Context 是不允许执行 I/O 操作(输入输出)的,包括读写文件、访问标准输入输出流、打开网络连接等。必要情况可通过context.allowIO(IOAccess.ALL)开启。

附录

源代码

本文所有源代码均在:⭐Java实用示例合集-GraalJS ⭐

参考资料

  • 全栈虚拟机GraalVM初体验
  • clever-graaljs:基于 graaljs 的高性能js脚本引擎,适合各种需要及时修改代码且立即生效的场景,如:ETL工具、动态定时任务、接口平台、工作流执行逻辑。 fast-api 就是基于clever-graaljs开发的接口平台,可以直接写js脚本开发Http接口,简单快速!
http://www.dtcms.com/a/402331.html

相关文章:

  • 辽宁省建设厅网站中级职称公示晚上网站推广软件免费版
  • 网站建设费归入长期待摊费用google推广专员招聘
  • 国外的ps网站餐饮网站建设推广
  • 如何拷贝别人网站的源码西安seo排名扣费
  • 卯兔科技网站建设seo外包公司是啥
  • 专业微信网站建设网站搭建免费模板
  • 凡科网的网站免费的可以用吗软件开发平台简介
  • 怎么维护网站电子商务与网站建设策划书
  • 深圳市城乡建设局网站南宁专业网站开发
  • 利用代码如何做网站wordpress采集英文
  • 建设网站的企业网站cms管理后台电话号码
  • 广州网站优化方式wordpress 柚子皮5.7
  • 高唐建筑公司网站网站开发的工资是多少
  • 杭州企业自助建站山东省建设厅网站地址
  • 常州网站建设效果杭州亚运会网页设计作业
  • linx服务器怎么做网站企业网站 响应式 案例
  • 化工行业网站设计百度网站关键字
  • 小语种网站建设及推广私域电商软件有哪些
  • 网站现在如何做推广网站建设的方法有哪些方面
  • 家居商城网站模板平台搭建教程
  • 网站自动发送邮件华为仓颉编程语言
  • 制作荧光字网站云浮北京网站建设
  • 免费网站的资源可以发公众号吗首页关键词是不是一个网站的核心关键词所在
  • 视频推广网站wordpress创意点赞
  • 青岛新网站设计公司国外室内设计网站推荐
  • 乐山 网站建设浙江中钦建设有限公司网站
  • 制作公司网站设计手绘新万网
  • 品牌推广是什么刷排名seo
  • 注册网站借钱平台犯不犯法网站如何做关键词优化
  • 常州网站建设流程2022最近热点事件及评述