介绍
在Truffle在神圣的Graal中服务:Graal和Truffle在JVM上进行多语种语言解释的帖子中,我们得到了简短的介绍,并对Graal,Truffle及其周围的一些概念进行了深入研究。 但是,如果不深入研究实用性,那么任何技术都不会很有趣,否则它就像理论物理学或纯数学一样-对某些人来说是抽象的,对其他人来说很无聊(对不起,最后一部分只是我的抱怨)。
在这篇文章中,我们将通过安装GraalVM ,比较SDK的差异以及一些示例来说明如何在GraalVM上编译和运行不同的语言,以及如何在GraalVM中运行它们,来研究GraalVM。相同的上下文,最后是本地语言(性能更高)。
GraalVM与我们从任何供应商处下载的任何Java SDK(JDK)相似,除了它具有JVMCI:Java级JVM编译器接口支持,并且Graal是默认的JIT编译器。 它不仅可以执行Java代码,还可以执行JS,Ruby,Python和R等语言。它还可以为Java程序和其他支持的语言构建提前(AOT)编译的可执行文件(本机映像)或共享库。 尽管我们不会遍历所有语言,但只会选择其中的几种。
只是让您知道,所有命令和操作都是在Ubuntu 16.04操作系统环境上执行的(应该在MacOSX上进行较小的改动,在Windows上需要更多的更改–很高兴收到有关差异的反馈,将与他们一起更新帖子)。
实际动手
我们可以通过多种方式使用GraalVM ,既可以自行构建它,也可以从供应商网站下载预构建的版本:
- 建立在我们自己的基础上:一些克隆和其他魔术(我们稍后会看到)
- 下载现成的JVM: OTN下载站点
- 将自定义JIT连接到具有JVMCI支持的现有JDK(我们将在后面看到)
由于我们使用的是Linux环境,因此最好下载基于JDK8 (> 500MB文件,需要接受许可,需要在OTN 上登录)的GraalVM的Linux(预览版)版本。 https://login.oracle.com/mysso/signon.jsp )并安装。
解压缩档案后,按照下载页面上的安装信息进行操作,执行以下命令后,您将找到一个名为graalvm-0.30
的文件夹(在撰写本文时)。
$ tar -xvzf graalvm-0.30-linux-amd64-jdk8.tar.gz
鹰眼:比较SDK
我们将快速检查SDK的内容以熟悉它们,因此让我们检查GraalVM SDK文件夹的内容:
$ cd graalvm-0.30
$ ls
与传统的Java SDK文件夹(即JDK 1.8.0_44)相比,它看起来很熟悉并且具有相似之处:
$ cd /usr/lib/jdk1.8.0_44
$ ls
除了我们还有很多其他要学习的工件,即VM上支持的语言的启动器,例如FastR,JS(GraalJS),NodeJS(GraalNodeJS),Python,Ruby和Sulong (C / C ++,Fortran) 。
比较GraalVM SDK和说JDK 1.8.0_44 SDK之间的bin
文件夹,我们可以看到那里有一些其他文件:
(使用诸如meld
或diff
类的工具来比较目录)
同样,我们可以看到jre
文件夹有一些有趣的差异,尽管其语义与传统的Java SDK相似。 列表中一些有趣的项目是Rscript , lli和ployglot 。
现在,我们还没有从字面上比较这两个SDK来标记彼此之间不同或缺失的元素,但是上面的内容使我们对预先使用其提供的功能提供了一个了解-该SDK具有他们将其放入了examples
文件夹。
$ tree -L 1
(使用tree
命令– sudo apt-get tree
可以看到以上内容,在MacOSX和Windows上可用)
每个子文件夹都包含GraalVM支持的各种语言的示例,包括我们还将介绍的embed
和native-image
。
令人兴奋的部分:动手使用示例
让我们开始讨论,但是在执行任何代码并查看示例做什么之前,我们应该将graalvm-0.30
移动到其他Java SDK所在的位置,在/ usr/lib/jvm/
进行设置,并设置环境变量调用GRAAL_HOME
指向它:
$ sudo mv -f graalvm-0.30 /usr/lib/jvm
$ export GRAAL_HOME=/usr/lib/jvm/graalvm-0.30
$ echo "export GRAAL_HOME=/usr/lib/jvm/graalvm-0.30" >> ~/.bashrc
$ cd examples
R语言
让我们选择R
并运行一些R
脚本文件:
$ cd R
$ $GRAAL_HOME/bin/Rscript --help # to get to see the usage text
注意我们正在运行Rscript
而不是R
,两者都可以运行R脚本,后面是R
REPL。
使用Rscript
运行hello_world.R
:
$ $GRAAL_HOME/bin/Rscript hello_world.R
[1] "Hello world!"
JavaScript
接下来,我们尝试一些Javascript
:
$ cd ../js/
$ $GRAAL_HOME/bin/js --help # to get to see the usage
使用js
运行hello_world.js
:
$ $GRAAL_HOME/bin/js hello_world.js
Hello world!
嵌入
现在让我们尝试一些不同的方法,如果您希望在JVM上运行用多种语言编写的代码,这些代码都驻留在同一个源文件中,这以前从未做过,这就是embed的意思。
$ cd ../embed
我们可以使用org.graalvm.polyglot.context
类来实现。 这是HelloPolyglotWorld.java
的代码片段:
import org.graalvm.polyglot.*;public class HelloPolyglotWorld {public static void main(String[] args) throws Exception {System.out.println("Hello polyglot world Java!");Context context = Context.create();context.eval("js", "print('Hello polyglot world JavaScript!');");context.eval("ruby", "puts 'Hello polyglot world Ruby!'");context.eval("R", "print('Hello polyglot world R!');");context.eval("python", "print('Hello polyglot world Python!');");}
}
使用下面的代码进行编译以创建一个.class
文件:
$ $GRAAL_HOME/bin/javac HelloPolyglotWorld.java
并使用以下命令运行它以查看其工作原理:
$ $GRAAL_HOME/bin/java HelloPolyglotWorld
Hello polyglot world Java!
Hello polyglot world JavaScript!
Hello polyglot world Ruby!
[1] "Hello polyglot world R!"
Hello polyglot world Python!
在语言之间进行切换并打印“ Hello多种语言世界……”时,您可能已经注意到执行过程有些迟钝。 消息,希望我们能够了解为什么会发生这种情况,甚至可以解决它。
本机图像
GraalVM SDK的本机映像功能有助于缩短 Java应用程序的启动时间 ,并减小其占用空间 。 有效地将其在JVM(在任何平台上)上运行的字节码转换为特定OS /平台的本机代码-这就是性能的来源。 它使用积极的提前(aot)优化来获得良好的性能。
让我们看看它是如何工作的。
$ cd ../native-image
让我们从此文件夹中的HelloWorld.java
中提取Java代码段:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
编译成字节码:
$ $GRAAL_HOME/bin/javac HelloWorld.java
将字节码(HelloWorld.class)编译为本机代码:
$ $GRAAL_HOME/bin/native-image HelloWorldclasslist: 740.68 ms(cap): 1,042.00 mssetup: 1,748.77 ms(typeflow): 3,350.82 ms(objects): 1,258.85 ms(features): 0.99 msanalysis: 4,702.01 msuniverse: 288.79 ms(parse): 741.91 ms(inline): 634.63 ms(compile): 6,155.80 mscompile: 7,847.51 msimage: 1,113.19 mswrite: 241.73 ms[total]: 16,746.19 ms
看一下文件夹,我们可以看到Hello World源代码和已编译的工件:
3.8M -rwxrwxr-x 1 xxxxx xxxxx 3.8M Dec 12 15:48 helloworld12K -rw-rw-r-- 1 xxxxx xxxxx 427 Dec 12 15:47 HelloWorld.class12K -rw-rw-r-- 1 xxxxx xxxxx 127 Dec 12 13:59 HelloWorld.java
第一个文件helloworld是本机二进制文件,它使用native-image命令在我们对其进行编译的平台上运行,该命令可以在JVM的帮助下直接执行:
$ helloworld
Hello, World!
即使我们获得了性能,但我们可能会失去在JVM上以字节码形式运行的其他功能-选择哪种路由完全取决于用例和重要性为了我们。
总结一下!
这需要进行总结,在命令行上有很多阅读和尝试的经验,但是值得花时间探索有趣的GraalVM。
总而言之,我们着手从Oracle Lab网站下载GraalVM,将其解压缩,查看各种文件夹,并将其与我们传统的Java SDK进行比较,并注意到并指出了差异。
我们进一步查看了为各种Graal支持的语言提供的示例,并挑选了一些功能,这些功能使我们对GraalVM可以提供的功能有所了解。 尽管我们可以在其上运行传统的Java应用程序,但现在我们也有机会在同一源文件或同一项目中编写以多种支持的语言表示的应用程序。 这也使我们能够在以不同语言编写的应用程序的不同方面之间进行无缝互操作 。 甚至可以针对本机环境重新编译我们现有的应用程序( native-image ),以提高性能并减少占用空间。
翻译自: https://www.javacodegeeks.com/2017/12/learning-use-wholly-graalvm.html