最流行的 WebAssembly 语言,会是 JavaScript 吗?( 三 )


你可以使用 Java 来编写 WebAssembly 模块,但 Cosmonic 首席执行官 Liam Randall 表示:“在未来几个月,字节码联盟将推出重大更新,提供更多的 Java 支持 。”
Randall 说道:“今年构建、创建和操作组件的能力方面取得了重大进展,其中最重要的两种语言分别是 Rust 和 Java 。”
目前,最流行的方法是使用 QuickJs 解释器(最初由 Shopify 采用并推广,这个包非常小,只有 210KB),许多 WebAssembly 运行时中都包含这个包 。例如,Shopify 的 Javy 和 Fermyon 的 spin-js-sdk 都使用了Quickjs 与 Wasmtime 运行时(早期与 Type 绑定,但尚未将 Java 作为官方支持的语言),而且还有一个面向 CNCF WasmEdge 运行时的 QuickJS 版本,既支持在 WebAssembly 中使用 Java,而且也允许在 Java 中调用 C/C++ 和 Rust 函数 。
QuickJs 支持 ECMA 2020 的大部分功能,包括字符串、数组、对象以及支持它们的方法、异步生成器、JSON 解析、正则表达式、ES 模块和可选的运算符重载、BigDecimal 和 BigFloat 。所以,这个包可以运行大部分Java代码 。除了比较小之外,这个包还非常快,并为运行 Java 提供了良好的性能——但它不支持 JIT 。
使用 QuickJs 可以有效地捆绑在 Java 运行时中,而且这种简约有一个很大的好处,Hayes 指出:“通常包的规模越大,性能就无法做到完美,但大多数情况下依然可以正常使用,我看到很多地方都采用了这个包 。”
Fermyon 的 Java SDK 建立在基于QuickJs的Javvy 之上,同时还使用了 Wizer 预初始化来保存代码初始化后的快照,从而加快 QuickJs 的启动时间 。Butcher 解释道,“Wizer 可以加快 .NET 在 WebAssembly 上的运行速度,它从运行时开始,加载 .NET 的所有运行时环境,然后将其作为新的 WebAssembly 模块写回磁盘 。我们发现使用QuickJs也可以采用相同的方法 。”
“在允许spin构建时,SDK会获取 Java 运行时,获取源文件,使用 WIZER 对其进行优化,然后将所有这些打包并发送到一个新的 WebAssembly 二进制文件中 。”
通过预优化解释型语言的代码来提高速度的思路听起来很熟悉,因为大多数浏览器的 Java 引擎就采用了这种方法 。“引擎在解释Java的同时将Java文件发送给优化器,只需几毫秒,就可以从解释模式切换到编译优化模式 。”
“不为人知的是,实际上WebAssembly集合了我们从 Java、Java、.NET 积累的一切经验 。我们在过去的15~20年间使用这些语言积累的经验的基础之上,构建了WebAssembly 。”
添加 JIT
Shopify 还与 Igalia 签约,将 Mozilla Java 引擎 SpiderMonkey 引入 Wasm;而 Fastly 则采用了 compontentize-js 法,使用 SpiderMonkey 以在浏览器中以高速模式运行 WebAssembly 的 Java 代码,由 JIT 负责编译 Java 代码并在 WebAssembly 解释器中运行 。
【最流行的 WebAssembly 语言,会是 JavaScript 吗?】尽管 WebAssembly 模块具备充分的可移植性,可以在许多不同的地方使用,但将多个 Wasm 模块组合成一个程序非常不容易 。Wasm 中的类型支持很原始,各种模块可能需要的不同 WebAssembly 功能,而这些功能被分组到不同的“世界”(如 Web、云和 CLI),并且每个模块通常都会定义自己的本地地址空间 。
Bedford 表示,“WebAssembly 的问题在于,获得某个二进制文件后,实际上你得到的只是非常低级的绑定函数,接下来你需要付出大量努力才能将所有二进制文件连起来 。你必须专门花精力连接每种语言,需要对输入输出的数据进行复杂的变换处理,所以你必须是一个非常有经验的开发人员才能知道如何处理 。”
WebAssembly 的组件模型添加了依赖项描述以及高级的、独立于语言的接口,用于传递值和指针 。这些接口解决了上述所说的“完全不共享内存空间的高级封装问题” 。
他解释道,“你有的不只是一个盒子,而是一个带有接口的盒子,盒子之间可以互相交谈 。你可以拥有函数和不同类型的结构以及对象结构,你还可以拥有跨越组件边界的数据结构 。”
Compontentize-js 就建立于此基础之上,允许开发人员使用任意绑定 。“我们可以根据你的绑定和想要运行的 Java 模块,给你一个 WebAssembly 二进制文件,它代表整个 Java 运行时和拥有这些绑定的引擎 。我们可以非常快速地提供这个二进制文件,而且可以生成非常复杂的绑定 。”
这个过程不需要很多额外的 WebAssembly 构建步骤,Java 开发人员可以使用熟悉的工具,并通过 npm 安装库 。
尽管从规模上看,SpiderMonkey 比 QuickJs 更大(Bedford 估计带有 Java 运行时的二进制文件和开发人员的 Java 模块大约为5~6MB),但依然非常小,足以快速初始化,可用于边缘计算硬件 。


推荐阅读