首页 体育 教育 财经 社会 娱乐 军事 国内 科技 互联网 房产 国际 女人 汽车 游戏

使用 GraalVM 开发多语言应用

2020-01-02

多言语开发 关于 Java 和 JVM 言语来说,能够直接运用 GraalVM 中的 Java 编译器进行编译,运用 Java 虚拟机来运转。除了 Java 和 JVM 言语之外的其他言语,都是根据 Truffle 结构完成的,能够运用多言语 API 来进行互操作。这种互操作不只限于 JVM 言语和其他言语之间,这些言语之间也能进行互操作。比方,能够在 JavaScript 代码中调用 Ruby 言语。除了 Java 和 JVM 言语之外,其他根据 Truffle 结构完成的言语都称为访客言语。在 Java 运用中,运用 GraalVM 的多言语开发功用需求用到 GraalVM 的 Java SDK。该 SDK 的 JAR 文件 graal-sdk.jar 现已包含在 GraalVM 的 jre/lib/boot 目录中,能够直接运用。在开发中,能够把该 JAR 文件作为 JDK 的一部分增加到 IDE 中,以保证代码能够在 IDE 中编译。也能够运用 Maven 增加对 GraalVM SDK 的依靠,如代码清单 1 所示。

 dependency 
 groupId org.graalvm.sdk /groupId 
 artifactId graal-sdk /artifactId 
 version 19.2.0.1 /version 
 scope provided /scope 
 /dependency 

代码清单 2 给出了运转 JavaScript 代码的 Java 示例。

import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;
public class JsEvaluation {
 public static void main {
 try ) {
 Value date = context.eval.toString 
 System.out.println);
}

绑定目标 在履行言语代码时,能够经过绑定目标在代码运转的顶层域中设置值。代码清单 3 运用 Context 供给的构建器来创立 Context 目标,其间 allowAllAccess 的作用是答应访客言语取得对宿主环境的彻底拜访。在运用 Context 目标的 getBindings 办法得到指定言语的绑定目标之后,再经过 putMember 办法来设置值。这儿设置的是一个 Java 中的 HashMap 目标。在 JavaScript 代码中,经过绑定目标设置的值作为全局变量呈现,因而能够直接运用。

public class JsBindings {
 public static void main {
 try .allowAllAccess.build) {
 Value bindings = context.getBindings;
 data.put;
 Value content = context.eval 
 System.out.println);
}

清单 4. 运用@HostAccess.Export 注解敞开的办法

public class JsHostAccess {
 public static void main {
 try ) {
 Pointer pointer = new Pointer;
 context.getBindings.putMember;
 Pointer movedPointer = context.eval ).as;
 System.out.println;
 public static class Pointer {
 private final int x;
 private final int y;
 Pointer {
 this.x = x;
 this.y = y;
 @Export
 public int getX {
 return x;
 @Export
 public int getY {
 return y;
 @Export
 public Pointer move {
 return new Pointer;
 @Override
 public String toString {
 return String.format;
}
在 JavaScript 中调用 Java 在访客言语中也能够调用 Java。代码清单 5 中的 JavaScript 代码运用了 Java 中的 java.time.Instant 类。 Java.type 办法能够加载指定的 Java 类。Java 类的静态办法能够直接调用,也能够运用 new 来创立目标。

public class JsHostAccess {
 public static void main {
 try ) {
 Pointer pointer = new Pointer;
 context.getBindings.putMember;
 Pointer movedPointer = context.eval ).as;
 System.out.println;
 public static class Pointer {
 private final int x;
 private final int y;
 Pointer {
 this.x = x;
 this.y = y;
 @Export
 public int getX {
 return x;
 @Export
 public int getY {
 return y;
 @Export
 public Pointer move {
 return new Pointer;
 @Override
 public String toString {
 return String.format;
}
var Instant = Java.type;
var ChronoUnit = Java.type;
print);
var nowPlus30Days = Instant.now.plus;
print;

清单 6. 在 JavaScript 中调用 Ruby

var array = Polyglot.eval;
print;
代码清单 6 中的 polyglot.js 文件需求运用 node --jvm --polyglot polyglot.js 指令来运转。其间参数 --jvm 表明表明在 Java 虚拟机上运转 JavaScript 代码,而 --polyglot 表明启用多言语 API。

var array = Polyglot.eval;
print;

清单 7. 完好的 NodeJS 多言语示例

const http = require
const url = require
const port = 3000
const BigInteger = Java.type
const requestHandler =  = {
 try {
 const {query} = url.parse
 const {base, exponent} = query
 const result = ).pow)
 response.end)
 } catch  {
 console.error
 response.end
const server = http.createServer
server.listen = {
 if  {
 return console.log
 console.log
})
该 JavaScript 文件的名称为 pow.js 。在运转时,只需求用 GraalVM 供给的 node 指令即可。详细的指令是 node --jvm --polyglot pow.js 。除了运用言语自身的指令行东西运转代码之外,还能够运用 polyglot 指令来运转,如 polyglot --jvm pow.js 。运用 polyglot 指令的优点是能够指定多个不同言语的文件,如 polyglot --jvm app.js app.rb app.py 。

const http = require
const url = require
const port = 3000
const BigInteger = Java.type
const requestHandler =  = {
 try {
 const {query} = url.parse
 const {base, exponent} = query
 const result = ).pow)
 response.end)
 } catch  {
 console.error
 response.end
const server = http.createServer
server.listen = {
 if  {
 return console.log
 console.log
})

构建原生镜像 运转 Java 运用都需求 Java 虚拟机的支撑。即便是最简略的输出 Hello World 的 Java 运用也需求一个完好的 Java 虚拟机才干运转。Java 虚拟机除了占有硬盘和内存空间之外,也使得 Java 运用的分发和布置变得复杂。GraalVM 供给的原生镜像功用能够把 Java 代码预先编译成独自的可履行文件,称为原生镜像。该可履行文件包含了运用自身的代码、所依靠的第三方库和 JDK 自身。该履行文件并不是运转在 Java 虚拟机之上,而是名为 Substrate 的虚拟机。与运转在传统的 Java 虚拟机上比较,原生镜像运转时的发动速度更快,所消耗的内存资源更少。以根据 GraalVM 的 Quarkus 库为例,运用 Quarkus 和 GraalVM 的 REST 运用的发动时刻仅为 13 毫秒,占用内存仅 13MB;而传统的根据 Java 虚拟机的 REST 运用的发动时刻需求 4.3 秒,占用内存为 140MB。

代码清单 8 中是最简略的输出 Hello World 的 Java 运用的源代码 HelloWorld.java 。在运用 javac 指令编译该文件之后,得到对应的 HelloWorld.class 文件。接着运用 native-image HelloWorld hello 指令能够从该 class 文件中发生名为 hello 的可履行文件。终究发生的 hello 2.2MB,节省了十分多的磁盘空间。

public class HelloWorld {
 public static void main {
 System.out.println
办法来加载类时,假如给出的类名是常量,对应的 Java
 类会被增加。不过静态剖析有它的局限性。假如 Class.forName
办法的参数是一个变量,就无法包含所实践对应的类,然后在运转时发生过错。关于这样的状况,能够经过装备文件来指定运转时需求的类和办法。 

除了反射 API 的约束之外,Java 7 中引进的 invokedynamic 指令和办法句柄也无法在 GraalVM 原生镜像中运用。Java 目标的 finalizer 也是不支撑的。由于没有动态类加载,Java 的安全办理器实践上是不需求的。Java 供给的办理和调试功用也是不支撑的,包含 JVMTI、JMX 和其他虚拟机接口。这些是 Java 运用运转在一般 Java 虚拟机和以 GraalVM 原生镜像运转时的差异。由于这些差异,并不是一切运用都能够直接编译成原生镜像,或许需求增加相关的装备。不同第三方库对原生镜像的支撑也不尽相同。Spring 结构计划在 5.3 版别中供给对原生镜像的完好支撑。在原生镜像发生之后,需求进行很多的测试以保证不呈现问题。考虑到 GraalVM 原生镜像所能带来的巨大的功用提高,对已有的运用进行改动以支撑 GraalVM 原生镜像的支付是值得的。

GraalVM 相关东西

下面临 GraalVM 供给的相关东西进行介绍。

GraalVM 对根据 Truffle 结构的言语都供给了长途调试的功用。GraalVM 完成了 Chrome DevTools 协议,能够经过 Chrome 开发者东西连接到 GraalVM 上运转的代码进行调试。只需求在运转时增加 --inspect 参数,就能够发动 GraalVM 内置的调试服务。进行调试的 URL 地址会被输出到控制台,只需求翻开 Chrome 浏览器拜访该地址即可。能够在 Chrome 开发者东西中翻开源文件并增加断点进行调试。

功用评价 GraalVM 关于根据 Truffle 结构的言语供给了功用评价功用,能够剖析 CPU 和内存的运用状况,找出功用瓶颈。GraalVM 供给了三种不同的东西,见表 2。其间 --memtracer 现在是试验性功用,需求增加额定参数 --experimental-options 启用该功用。

表 2. GraalVM 供给的功用评价功用

除了反射 API 的约束之外,Java 7 中引进的 invokedynamic 指令和办法句柄也无法在 GraalVM 原生镜像中运用。Java 目标的 finalizer 也是不支撑的。由于没有动态类加载,Java 的安全办理器实践上是不需求的。Java 供给的办理和调试功用也是不支撑的,包含 JVMTI、JMX 和其他虚拟机接口。这些是 Java 运用运转在一般 Java 虚拟机和以 GraalVM 原生镜像运转时的差异。由于这些差异,并不是一切运用都能够直接编译成原生镜像,或许需求增加相关的装备。不同第三方库对原生镜像的支撑也不尽相同。Spring 结构计划在 5.3 版别中供给对原生镜像的完好支撑。在原生镜像发生之后,需求进行很多的测试以保证不呈现问题。考虑到 GraalVM 原生镜像所能带来的巨大的功用提高,对已有的运用进行改动以支撑 GraalVM 原生镜像的支付是值得的。

下面临 GraalVM 供给的相关东西进行介绍。

功用评价 GraalVM 关于根据 Truffle 结构的言语供给了功用评价功用,能够剖析 CPU 和内存的运用状况,找出功用瓶颈。GraalVM 供给了三种不同的东西,见表 2。其间 --memtracer 现在是试验性功用,需求增加额定参数 --experimental-options 启用该功用。

热门文章

随机推荐

推荐文章