在很多场景下,我们都有从java调用脚本的功能,常用的有groovy脚本,pyhon脚本和js等。在 上篇 中,列举了java调用pyhton脚本的几种方案,并最终选取了JEP的方式,但是随着业务的提升,JEP由于GIL锁的问题,每次只能执行一次脚本,并发高的情况下,由于资源竞争,JEP会变得非常慢,于是需要新的方案来解决这个问题。

GraalVM介绍

通过查阅资料,找到了一种可行的方案,首先我们了解下什么是 GraalVM

GraalVM 是一款基于 Java 虚拟机 (JVM) 的新型全栈虚拟机,由 Oracle 公司开发和维护。GraalVM 除了支持 Java 语言之外,还支持多种编程语言,如 JavaScript、Python、Ruby、R 等。

GraalVM 的主要特点包括:

  • 高性能:GraalVM 基于 JIT (Just-in-time) 编译技术,在运行时动态生成本地代码,可以显著提高程序的性能。
  • 多语言支持:GraalVM 支持多种编程语言,并可以在不同的语言之间进行互操作。
  • 低内存占用:GraalVM 使用了一种名为 GraalVM Native Image 的技术,可以将应用程序编译成本地可执行文件,从而减少内存占用和启动时间。
  • 可扩展性:GraalVM 提供了多种插件和扩展点,可以方便地扩展虚拟机的功能和性能。
  • GraalVM 还提供了多种工具和库,如 GraalVM Compiler、GraalVM Truffle、GraalVM Polyglot 等,可以帮助开发人员更好地使用和优化 GraalVM。

使用GraalVM实现python脚本

GraalPython 是基于 GraalVM 平台的 Python 解释器,由 Oracle 公司和社区开发维护。它支持 Python 3.7 语言规范,并且与 CPython 兼容,可以运行大部分的 Python 代码。

GraalPython 的主要特点包括:

  • 高性能:GraalPython 使用了 GraalVM 平台的 JIT 编译器技术,可以将 Python 代码编译成本地代码,提高程序的执行效率。
  • 多语言互操作:GraalPython 支持 GraalVM 平台的 Polyglot API,可以与其他编程语言进行互操作。
  • 执行安全:GraalPython 支持沙箱机制,可以限制 Python 代码的访问权限,保证执行安全。
  • 可扩展性:GraalPython 提供了多种扩展点和插件机制,可以方便地扩展其功能和性能。
    GraalPython 与 CPython 之间的差异主要在于其内部实现机制。GraalPython 使用了 GraalVM 平台的 Truffle 框架,将 Python 代码转换为 AST (抽象语法树) 并进行优化,然后使用 JIT 编译器生成本地代码。相比之下,CPython 是使用 C 语言实现的,其执行速度较慢,但兼容性更好,可以运行大部分的 Python 代码。

需要使用GraalPython,我们首先要搭建GraalPython环境
安装 GraalVM:下载 GraalVM 安装包并解压缩,然后将其添加到环境变量中。可以参考官方文档:https://www.graalvm.org/docs/getting-started/linux/。

安装 GraalPython:打开终端,执行以下命令安装 GraalPython:

gu install python

该命令会自动安装最新版本的 GraalPython。
验证 GraalPython:执行以下命令验证 GraalPython 是否安装成功:

python --version

如果输出 Python 的版本信息,则说明 GraalPython 安装成功。

使用 GraalPython:在终端中执行以下命令启动 GraalPython 解释器:

graalpython

然后就可以在 GraalPython 环境中运行 Python 代码了。

安装好GraalPython后,我们需要构建venv环境, venv是 Python 3 自带的一个标准库,它可以帮助用户创建虚拟环境,使得不同的项目之间的依赖关系和库版本隔离开来,从而避免了不同项目之间的库冲突和版本不兼容等问题。

使用 venv 创建虚拟环境非常简单,可以按照以下步骤操作:

打开终端,进入项目的根目录,执行以下命令创建虚拟环境:

graalpy -m venv /home/appuser/venv

上述命令将在当前目录下创建名为 myenv 的虚拟环境。

激活虚拟环境:执行以下命令激活虚拟环境:

source /home/appuser/venv/bin/activate

执行上述命令后,终端的提示符会变为 (myenv),表示虚拟环境已经激活。
在这里插入图片描述

在虚拟环境中安装依赖:执行以下命令安装需要的依赖:

pip install package_name

在虚拟环境中安装的依赖包仅对当前项目有效,不会影响系统中的其他项目。

退出虚拟环境:执行以下命令退出虚拟环境:

deactivate

执行上述命令后,终端的提示符会恢复为原来的样子。

需要注意的是,每次进入项目的开发环境时,都需要激活虚拟环境,否则无法使用虚拟环境中的依赖和库。

环境准备好后,我们就可以使用java环境调用python脚本。

  1. 首先导入sdk包
        <dependency>
            <groupId>org.graalvm.sdk</groupId>
            <artifactId>graal-sdk</artifactId>
            <version>22.3.1</version>
        </dependency>
  1. 然后编写代码
    private static final String PYTHON = "python";
    private static final String PYTHON_PYTHON_PATH = "python.PythonPath";
    private static final String PYTHON_EXECUTABLE = "python.Executable";
    private static final String PYTHON_FORCE_IMPORT_SITE = "python.ForceImportSite";
    private static Context createContext(String modulePath){
        Engine engine = Engine.create();
        Context context =  Context.newBuilder(PYTHON).allowAllAccess(true).engine(engine)
            .option(PYTHON_FORCE_IMPORT_SITE, "true")
            .option(PYTHON_PYTHON_PATH, modulePath)
            .option(PYTHON_EXECUTABLE, customizeConfig.getPythonExecutable())
            .build();
        return context;
    public static void main(String[] args) {
        Context context = createContext();
        Value bindings = context.getBindings(PYTHON);
        bindings.putMember("a", 1);
        bindings.putMember("b", 2);
        int i = context.eval(PYTHON, "a+b").asInt();
        System.out.println(i);

讲解下关键参数:

  • python.PythonPath 导入外部py文件目录的地址,比如a/a.py
  • python.Executable隔离环境的地址,上文中的/home/appuser/venv
  • python.ForceImportSite 强制开启site,这个功能主要是需要使用第三方库,如requests,则需要在这配置参数,开启sitespackge目录,当然,我们也可以通过脚本中运行”import site“开启。

至此我们通过graalpy实现了java中调用python脚本,在测试过程中,当我们不适用三方库的时候,性能比较客观,但是当我们使用ForceImportSite后性能有显著下降,当然整体比JEP好很多。

在预言过程中发现每次创建上下文Context非常耗时,一次执行就需要4s多,后来才支持因为cpu内核导致的,我使用的环境是mac m1,下载使用的事GraalVM(amd64),而m1以上的需要下载GraalVM(aarch64)版本,更改后瞬间将速度提升到毫秒级别。
当然GraalVM针对python的试验阶段,一旦能适用,几乎可以毫无成本的引入js脚本的支持,平台引入这个工具具有很高的扩展性
另外,目前对于第三方库python库的支持不是特别兼容,需要继续摸索
官方支持的兼容包如下:

Cython
Keras_preprocessing
Markdown
Pillow
PyYAML
Werkzeug
absl_py
astor
atomicwrites
attrs
cassowary
certifi
chardet
cppy
cycler
dateutil
gast
h5py
hypothesis
idna
joblib
kiwisolver
lightfm
matplotlib
mock
more_itertools
numpy
packaging
pandas
pkgconfig
pluggy
protobuf
py
pybind11
pyparsing
pytest
pytest_parallel
python_dateutil
pythran
pytz
requests
scikit_learn
scipy
setuptools
setuptools_scm
six
sortedcontainers
threadpoolctl
tox
urllib3
wcwidth
wheel
zipp

是否使用GraalVM举要根据自己具体的使用场景去评估,如果只是简单的脚本调用就非常适合,性能客观,但是存在大量的第三方库和自定义库性能就会收到影响,同事需要考虑兼容问题。

*如果您想支持这些教程,可以向我的捐款 GraalVM Python 这是一个演示项目,说明如何使用GraalVM和Quarkus框架在Java应用程序中运行其他编程语言,例如Javascript和Python。 准备当地环境 您必须在Ubuntu OS上运行。 下载并配置GraalVM。 将GRAALVM_HOME设置为您提取GraalVM tar文件的位置。 将JAVA_HOME设置为GRAALVM_HOME。 将JAVA_HOME添加到PATH变量。 在GraalVM / bin文件夹中导航。 安装本机映像。 ./gu install native-image 在GraalVM中安装Python。 ./gu install python // check the available packages ./graalpython -m ginstall in PythonGraalVM实现这是Python的早期实验实现。 一个主要目标是支持SciPy及其组成库。 该Python实现目前旨在与Python的Pyth GraalVM实现兼容。这是Python的早期实验实现。 一个主要目标是支持SciPy及其组成库。 目前,此Python实现旨在与Python 3.7兼容,但是距此还有很长的路要走,任何需要任何软件包的Python程序很可能会遇到不受支持的情况。 至此,Python实现可供实验和好奇的最终用户使用PythonGraalVM实现 这是Python的早期实验实现。 一个主要目标是支持SciPy及其组成库。 GraalPython通常可以比CPython更快地执行纯Python代码(但涉及C扩展时则不能)。 GraalPython当前的目标是与Python 3.8兼容,但是距离那里还有很长的路要走,使用标准库模块或外部软件包的更多功能的任何Python程序很可能会遇到不受支持的情况。 至此,Python实现已可供实验和好奇的最终用户使用。 尝试GraalPython的最简单选择是Python版本管理器 。 它使您可以轻松安装不同的GraalPython版本。 例如,要获取版本20.2,只需运行pyenv install graalpython-20.2 。 要在完整的GraalVM上尝试GraalPython,包括对Java嵌入的支持以及与其他语言的互操作,可以使用的捆绑发 文章目录关于 GraalVM安装GraalVM Python使用 ginstall 安装第三方包graalpython 交互模式下执行 python 代码 关于 GraalVM GraalVM : a high-performance JDK distribution It is designed to accelerate the execution of applications written in Java and other JVM languages while also providing 前言2018年4月,Oracle Labs新公开了一项黑科技:Graal VM。这是一个在HotSpot虚拟机基础上增强而成的跨语言全栈虚拟机,可以作为“任何语言”的运行平台使用。现在网络上关于 Graal VM 的相关资料并不多,还是要看官方文档。本文旨在简要介绍:什么是 Graal VM?Graal VM 有什么好处?Graal VM 有什么缺点?Graal VM 的工作原理是什么?... 最近碰到几个人问,如何实现 java 调用他们写好的 Python 应用(模型),这里我就把几种常见的办法做下汇总整理。喜欢本文记得收藏、点赞。本文由技术群粉丝分享,项目源码、数据、技术交流提升,均可加交流群获取,群友已超过2000人,添加时最好的备注方式为:来源+兴趣方向,方便找到志同道合的朋友如使用 java 的 API, 2. 通过 REST API REST 是表现层状态转换(英语:Representational State Transfer)的英文缩写,是 Roy Thomas Fieldi GraalVM是开发人员编写和执行Java代码的工具。具体来说,GraalVM是由Oracle创建的Java虚拟机(JVM)和Java开发工具包(JDK)。它是一个高性能的运行时,可以提高应用程序的性能和效率。GraalVM的目标包括:编写一个更快、更易于维护的编译器,提高在JVM上运行的语言的性能,减少应用程序启动时间,将多语言支持集成到Java生态系统中,以及为此提供一组编程工具。GraalVM向JDK添加了一个优化编译器,它为各种语言提供性能优化,并为多语言应用程序提供互操作性。... 构建在GraalVM之上的一个Python 3实现 PythonGraalVM 实现 这是 Python 的早期实验实现。 一个主要目标是支持 SciPy 及其组成库。 这个 Python 实现目前的目标是与 Python 3.7 兼容,但距离那里还有很长的路要走,而且很可能任何需要任何包的 Python 程序都会遇到不受支持的东西。 此时,Python 实现可供实验和好奇的最终用户使用。 试用 要试用,您可以使用 www.graalvm.org 中的捆绑版本。 有关更多信息和您可以使用它做什么的一些示例,请查看参考资料。 创建虚拟环境 使用 PythonGraalVM 实现的最佳方式是脱离虚拟环境。 这将生成包装器脚本并使实现可从 shell 作为标准 Python 解释器使用。 为此,请在项目目录中执行以下操作: Build GraalPython: mx build 创建 venv: mx python -m venv 在 shell 会话调用中激活环境: source /bin/activate 在 venv 中可以使用多个可执行文件,例如 py 最近碰到几个人问,如何实现 java 调用他们写好的 Python 应用(模型),这里我就把几种常见的办法做下汇总整理。喜欢本文记得收藏、关注、点赞。 【注】文末提供技术交流群 李宏毅《机器学习》国语课程(2022)来了 有人把吴恩达老师的机器学习和深度学习做成了中文版 上瘾了,最近又给公司撸了一个可视化大屏(附源码) 如此优雅,4款 Python 自动数据分析神器真香啊 梳理半月有余,精心准备了17张知识思维导图,这次要讲清统计学 年终汇总:20份可视化大屏模板,直接套用 GraalVM有许多不同的组件,如果你只是听说过它或有些简单的了解,肯定无法一窥全豹。本文将列举下GraalVM的几大常用功能,看看它们都能做些什么。 高性能的现代Java 占用资源少,启动速度快 JavaScript, Java, Ruby以及R混合编程 在JVM上运行原生语言 跨语言工具 JVM应用扩展 原生应用扩展 本地Java库 数据库支持多语言 创建自己的语言 本文将要介绍的内容在Gra... 前阵子,Oracle 发布了一个黑科技 "GraalVM",号称是一个全新的通用全栈虚拟机,并具有高性能、跨语言交互等逆天特性,真有这么神奇? GraalVM 简介 GraalVM 是一个跨语言的通用虚拟机,不仅支持了 Java、Scala、Groovy、Kotlin 等基于 JVM 的语言,以及 C、C++...