GraalVM上的多语言混合开发

上篇文件我们介绍了GraalVM强大的静态编译功能,能够让Java应用程序摆脱虚拟机的束缚,像其它本地编译的应用一样直接运行。那么GraalVM的神奇之处仅限于此吗?今天我们再来看看它的另一个重要特性—多语言混合开发

多语言平台

Java并不是唯一运行在JVM上的语言,这个我们都应该比较清楚了,比如Kotlin,Scala,Groovy这些其实都是运行在JVM之上的。这样语言不管上层语法千差万别,但最终都会被编译器(javac,kotlinc等)编译成符合JVM规范的字节码,所以它们能跑在JVM上,并且可以相互调用其实并不让人意外。

理论上任何上层语言都能够通过一定的转换,变成符合标准JVM规范的字节码,从而运行在JVM平台之上,但编写这样的编译器的成本非常高,而且受限于JVM字节码的结构何规范,有些语言特性可能也没办法很好的支持。因此GraalVM实现多语言平台采用了另一种方式,绕开了JVM字节码的限制,我们先来看一下官方给的架构图:
在这里插入图片描述
在这张图上,不但GraalVM不但能跑Kotlin,Scala这类传统的JVM语言,还有JS, Python, Ruby这样的脚本语言,甚至还有C和C++ 。初看起来确实很让人惊讶,不过先别急,我们慢慢来分析一下其中的原理。这张图底层的部分,Graal编译器,JVMCI,Hotspot JVM上一篇文章都讲过了,不理解的同学可以再翻一下之前的文章。我们重点来看一下Truffle这个新出现的框架。

这个东西显然是实现多语言平台的关键,官方对它的定义有点拗口,简单的说它是一个用于开发某种语言(比如JavaScript)的解释器的一套工具和框架,让不同的语言能够方便的实现自己的解释器,从而将各语言的源代码都能够解析成一种统一的数据格式,而这种数据格式是一种self-modifying Abstract Syntax Trees(AST,抽象语法树)。为了便于理解,你可以简单的认为它就是其它语言编译后的字节码(都是某种中间格式),Truffle框架还提供运行层面的支持,可以直接解释执行这样的AST,从而实现多语言运行在JVM之上。因此要将一门现有语言搬到GraalVM上来运行,你只需要使用Truffle框架为该门语言编写一个Interpreter(解释器),是不是看起来很简单?GraalVM官方目前也已经实现了包括JavaScript,Python等在内的多个Truffle解释器(GraalJS,GraalPython等),可以直接供开发者使用。

在这里插入图片描述
如果仅仅是这样,那么大家可能觉得这仅仅只是一个小玩具而已,毕竟通过解释器来执行脚本语言性能肯定很拉跨,完全无法和原生平台的执行效率相提并论。但不要小看GraalVM的雄心壮志,我们都知道JVM经过这么多年的发展,在编译优化,内存管理(垃圾回收)这些方面都有着非常强悍的积累(go的垃圾回收器的性能表现就长期不如Java),这才是运行在JVM之上的语言的真正的优势所在。但怎么让这些解释执行的脚本语言也享受JVM的优化呢?答案是JIT,JIT的概念这里就不多介绍了,我们再来看一张图,以Javascript和Java为例,看看它们在GraalVM上的执行细节

运行细节

先来看Java的执行路径,首先由javac编译成字节码,然后JVM的解释器一边解释执行,一边收集运行时信息,当部分代码达到阙值的时候(调用次数等统计指标)就会触发JIT编译,JVM将此部分代码通过Graal编译器编译成本地机器码,然后替换自身缓存中的此部分字节码,从而提升该部分代码的执行效率。JVM和JIT编译器之间通过JVMCI规范的接口进行交互,所以这里的Graal编译器也可以替换成传统的C1或者C2编译器。Kotlin,Scala等语言的执行方式也基本是这样。

再看一下Javascript,源码首先会被基于Truffle实现的JS解释器转换成内存中的AST格式,然后就可以被Truffle内部的解释器解释执行了,而Truffle也会像JVM一样,统计收集运行时信息,并将热点代码发送给Graal编译器去编译成本地机器码,最终将编译好的机器码替换AST中的相同部分,所以现在明白为什么叫做self-modifying Abstract Syntax Trees吧,这个AST树是能够自修改的。所以基于Truffle框架执行的三方脚本语言,也能享受到JIT编译器的各种优化,性能比纯解释执行要高出很多。而且Truffle是一个完全用Java编写的框架,所以它可以直接运行于底层的JVM之上。

上面的图还有一个Graal IR的东西,这个是个什么东西呢?这个主要是为了让Graal编译器能够实现语言无关的特性而使用的一种中间表示形式,不管是JAVA的字节码还是Javascript的AST,在Graal编译器内部都会被表示为Graal IR,然后对这种格式进行编译优化,最终形成机器码。

通过精心的设计和优化,在GraalVM上执行三方语言,性能已经非常接近原生平台了,部分场景下甚至会超过原生的平台。下图就是GraalVM官方对于Javascript执行性能与V8(公认最强的JS执行引擎)的对比:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/42623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

����: �Ҳ������޷��������� javafx.fxml ԭ��: java.lang.ClassNotFoundException解决方法

如果你出现了这个问题,恭喜你,你应该会花很多时间去找解决方法。别问我怎么知道的... 解决方法: 出现乱码的原因:配置vm时 这些配置看似由有空格,换行,实则没有。所以解决办法就是,重新配置你…

防火墙概述

1、防火墙 防火墙顾名思义就是防止火灾发生时,火势烧到其它区域,使用由防火材料砌的墙。在网络安全中,防火墙的作用就是保护本地网络不受到外部网络或恶意程序的伤害。 防火墙的核心任务是控制和防护,即通过安全策略识别流量并做…

前端面试题17(js快速检索方法详解)

在前端JavaScript中,快速检索数据通常涉及到数组或对象的搜索。这里我会介绍几种常见的快速检索方法,并提供相应的代码示例。 1. 数组的find和findIndex方法 find: 返回数组中满足条件的第一个元素的值。findIndex: 返回数组中满足条件的第一个元素的索…

【mindspore进阶】02-ResNet50迁移学习

Mindspore 应用(2)ResNet50迁移学习 在实际应用场景中,由于训练数据集不足,所以很少有人会从头开始训练整个网络。普遍的做法是,在一个非常大的基础数据集上训练得到一个预训练模型,然后使用该模型来初始化…

张量分解(2)——张量运算(内积、外积、直积、范数)

🍅 写在前面 👨‍🎓 博主介绍:大家好,这里是hyk写算法了吗,一枚致力于学习算法和人工智能领域的小菜鸟。 🔎个人主页:主页链接(欢迎各位大佬光临指导) ⭐️近…

MATLAB贝叶斯线性回归模型案例

采用辛烷值数据集“spectra_data.mat”(任意数据集均可),介绍贝叶斯线性回归模型的构建和使用流程。 运行结果如下: 训练集预测精度指标如下: 训练集数据的R2为: 1 训练集数据的MAE为: 0.00067884 训练集数据的RMSE为: 0.0008893…

STM32点灯闪烁

stm32c8t6引脚图 开发板引脚图 GPIO端口的每个位可以由软件分别配置成 多种模式。 ─ 输入浮空 ─ 输入上拉 ─ 输入下拉 ─ 模拟输入 ─ 开漏输出 ─ 推挽式输出 ─ 推挽式复用功能 ─ 开漏复用功能 配置GPIO端口步骤:开启时钟->使用结构体设置输出模式…

水仙花数算法

一、水仙花的传说 希腊神话故事 传说希腊神话里,美少年纳西索斯(Narcissus)是希腊最俊美的男子,无数的少女对他一见倾心,可他却自负地拒绝了所有的人。这当中包括美丽的山中仙女伊可(Echo)。伊可…

分享一些提升效率的办公、学习神器!

分享一些提升效率的办公、学习神器! 文章目录 分享一些提升效率的办公、学习神器! 一、 ✅ 文件搜索工具 Everything:1.1 Everything 主要功能:1.2 Everything 下载地址: 二、 ✅ 文件压缩解压工具 7 - Zip&#xff1a…

AI免费英语学习在线工具:Pi;gpt;其他大模型AI 英语学习智能体工具

1、pi(强烈推荐:可以安卓下载使用) https://pi.ai/talk (网络国内使用方便) 支持实时聊天与语音对话 2、chatgpt(强烈推荐:可以安卓下载使用) https://chat.openai.com/ (网络国内使用不方便&#xf…

C++初学者指南-4.诊断---valgrind

C初学者指南-4.诊断—Valgrind Valgrind(内存错误检测工具) 检测常见运行时错误 读/写释放的内存或不正确的堆栈区域使用未初始化的值不正确的内存释放,如双重释放滥用内存分配函数内存泄漏–非故意的内存消耗通常与程序逻辑缺陷有关&#xf…

Halcon 背景网格产品刮伤缺陷检测

* 关闭窗口 dev_close_window ()*关闭程序计数器,图形变量更新,窗口图形更新 dev_update_off ()*设置图像路径 Path : lcd/mura_defects_blur_*读取一张图像 read_image (Image, Path 01)*获取图像大小 get_image_size (Image, Width, Height)*创建一个新窗体 dev_open_window…

Apache Seata应用侧启动过程剖析——注册中心与配置中心模块

本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。 本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。 Apache Seata应用侧启动过程剖析——注册中心与配置中心模块 前言 在Seata的应用侧&#xf…

强化训练:day13(牛牛冲钻五、最长无重复子数组、重排字符串)

文章目录 前言1. 牛牛冲钻五1.1 题目描述1.2 解题思路1.3 代码实现 2. 最长无重复子数组2.1 题目描述2.2 解题思路2.3 代码实现 3. 重排字符串3.1 题目描述3.2 解题思路3.3 代码实现 总结 前言 1. 牛牛冲钻五   2. 最长无重复子数组   3. 重排字符串 1. 牛牛冲钻五 1.1 题…

llama2阅读: logits是什么?

Logits是一个在深度学习中,几乎一直都有的概念,它意味着模型unnormalized final scores. 然后你可以通过softmax得到模型针对你class的概率分布。 而在llama2的代码中,同样有logits的使用,那么针对llama2,logits的作用…

Sequelize 操作 MySQL 数据库

安装 npm install --save sequelize安装驱动程序: npm install --save mysql2连接到数据库 要连接到数据库,必须创建一个 Sequelize 实例. 这可以通过将连接参数分别传递到 Sequelize 构造函数或通过传递一个连接 URI 来完成: const {Sequelize} re…

Canal架构以及使用规范

Canal架构以及使用规范 一、Canal的作用 相关文档:GitHub - alibaba/canal: 阿里巴巴 MySQL binlog 增量订阅&消费组件 MySQL主备复制原理 MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events,可…

Gitlab代码管理工具安装配置

前言: 没有真正的证书与域名建议使用httpip的方式在内网使用,不建议使用假的域名地址 一、安装前配置 #更改主机域名 hostnamectl set-hostname gitlab.dome.com bash #配置hosts 底部添加下面内容 vim /etc/hosts ############################ ip gi…

Stowaway搭建隧道打CFS内网靶场

目录 渗透带出主机阶段 先把我们的服务端上传到kali ​先把我们的客户端上传到目标机 客户端去连接我们的kali机端口去上线 出现admin,上线成功 detail相当于msf的sessions​ 和msf差不多功能,但是我们用它主要是搞隧道代理 抓发的 ​开启socks…

[终端安全]-4 移动终端之硬件架构安全

1 移动终端硬件架构 上图图展示了典型移动终端硬件架构,包括应用处理器(AP)、基带处理器(BP)以及各类共享组件和外设,所有组件通过AXI总线(和APB桥)连接在一起。以下分别介绍基于整…