You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2023/02/02 05:06:48 UTC

[shardingsphere] branch master updated: Introduce Truffle Espresso to make GroovyShell available under GraalVM Native Image and update GraalVM Reachability Metadata Repository to 0.2.6 (#23873)

This is an automated email from the ASF dual-hosted git repository.

zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 7e12ccdef4a Introduce Truffle Espresso to make GroovyShell available under GraalVM Native Image and update GraalVM Reachability Metadata Repository to 0.2.6 (#23873)
7e12ccdef4a is described below

commit 7e12ccdef4a607fa5651f291903adff73df3080d
Author: Ling Hengqian <li...@outlook.com>
AuthorDate: Thu Feb 2 13:06:41 2023 +0800

    Introduce Truffle Espresso to make GroovyShell available under GraalVM Native Image and update GraalVM Reachability Metadata Repository to 0.2.6 (#23873)
---
 .github/workflows/nightly-build-artifact.yml       |   2 +-
 distribution/proxy-native/Dockerfile               |  10 +-
 distribution/proxy-native/pom.xml                  |   3 +
 .../proxy-native/src/main/release-docs/LICENSE     |  11 +-
 .../release-docs/licenses/LICENSE-truffle-api.txt  |  35 +++++
 distribution/proxy/src/main/release-docs/LICENSE   |   9 ++
 .../release-docs/licenses/LICENSE-truffle-api.txt  |  35 +++++
 .../startup/graalvm-native-image.cn.md             |  46 +++---
 .../startup/graalvm-native-image.en.md             |  33 ++--
 infra/pom.xml                                      |   1 +
 infra/{util => util-groovy}/pom.xml                |  18 +--
 .../expr/HotspotInlineExpressionParser.java}       |   4 +-
 .../expr/HotspotInlineExpressionParserTest.java}   |  30 ++--
 infra/util/pom.xml                                 |  57 ++++++-
 .../util/expr/EspressoInlineExpressionParser.java  |  96 ++++++++++++
 .../infra/util/expr/InlineExpressionParser.java    | 170 +++++----------------
 .../util/expr/InlineExpressionParserTest.java      |  10 +-
 pom.xml                                            |  20 ++-
 18 files changed, 391 insertions(+), 199 deletions(-)

diff --git a/.github/workflows/nightly-build-artifact.yml b/.github/workflows/nightly-build-artifact.yml
index d09166afca5..0b9a23d5ae8 100644
--- a/.github/workflows/nightly-build-artifact.yml
+++ b/.github/workflows/nightly-build-artifact.yml
@@ -116,7 +116,7 @@ jobs:
         with:
           version: '22.3.1'
           java-version: '17'
-          components: 'native-image'
+          components: 'espresso,native-image'
           github-token: ${{ secrets.GITHUB_TOKEN }}
           cache: 'maven'
       - uses: docker/login-action@v2
diff --git a/distribution/proxy-native/Dockerfile b/distribution/proxy-native/Dockerfile
index 4d10a573be0..4452ec0d486 100644
--- a/distribution/proxy-native/Dockerfile
+++ b/distribution/proxy-native/Dockerfile
@@ -23,10 +23,14 @@ FROM oraclelinux:9-slim
 
 MAINTAINER ShardingSphere "dev@shardingsphere.apache.org"
 
-COPY --from=prepare /conf/ /conf
+ENV LOCAL_PATH /opt/shardingsphere-proxy-native
+
+bash <(curl -sL https://get.graalvm.org/jdk) -c espresso graalvm-ce-java17-22.3.1
+
+COPY --from=prepare /conf/ ${LOCAL_PATH}/conf
 
 ARG APP_NAME
 
-ADD target/${APP_NAME} ./
+ADD target/${APP_NAME} ${LOCAL_PATH}/
 
-ENTRYPOINT ./${APP_NAME} 3307 /conf
+ENTRYPOINT ${LOCAL_PATH}/${APP_NAME} 3307 ${LOCAL_PATH}/conf
diff --git a/distribution/proxy-native/pom.xml b/distribution/proxy-native/pom.xml
index 1e42518e118..8470a33acdf 100644
--- a/distribution/proxy-native/pom.xml
+++ b/distribution/proxy-native/pom.xml
@@ -100,6 +100,7 @@
             <id>native</id>
             <properties>
                 <hikari-cp.version>5.0.1</hikari-cp.version>
+                <truffle-api.version>22.3.1</truffle-api.version>
             </properties>
             <build>
                 <plugins>
@@ -124,6 +125,7 @@
                             <fallback>false</fallback>
                             <verbose>true</verbose>
                             <buildArgs>
+                                <arg>--language:java</arg>
                                 <arg>--report-unsupported-elements-at-runtime</arg>
                             </buildArgs>
                             <jvmArgs>
@@ -131,6 +133,7 @@
                             </jvmArgs>
                             <metadataRepository>
                                 <enabled>true</enabled>
+                                <version>0.2.6</version>
                             </metadataRepository>
                         </configuration>
                         <executions>
diff --git a/distribution/proxy-native/src/main/release-docs/LICENSE b/distribution/proxy-native/src/main/release-docs/LICENSE
index 9ed1877c9fc..8ddb2088c22 100644
--- a/distribution/proxy-native/src/main/release-docs/LICENSE
+++ b/distribution/proxy-native/src/main/release-docs/LICENSE
@@ -357,4 +357,13 @@ The text of each license is also included at licenses/LICENSE-[project].txt.
     checker-qual 3.5.0: https://github.com/typetools/checker-framework/blob/master/checker-qual, MIT
     jul-to-slf4j 1.7.36: https://www.slf4j.org, MIT
     slf4j-api 1.7.36: https://www.slf4j.org, MIT
-    jnanoid 2.0.0: https://github.com/aventrix/jnanoid, MIT 
+    jnanoid 2.0.0: https://github.com/aventrix/jnanoid, MIT
+
+========================================================================
+UPL licenses
+========================================================================
+
+The following components are provided under the UPL License. See project link for details.
+The text of each license is also included at licenses/LICENSE-[project].txt.
+
+    truffle-api 22.3.1: http://www.graalvm.org/, UPL
diff --git a/distribution/proxy-native/src/main/release-docs/licenses/LICENSE-truffle-api.txt b/distribution/proxy-native/src/main/release-docs/licenses/LICENSE-truffle-api.txt
new file mode 100644
index 00000000000..d656a31cb15
--- /dev/null
+++ b/distribution/proxy-native/src/main/release-docs/licenses/LICENSE-truffle-api.txt
@@ -0,0 +1,35 @@
+The Universal Permissive License (UPL), Version 1.0
+
+Subject to the condition set forth below, permission is hereby granted to any
+person obtaining a copy of this software, associated documentation and/or
+data (collectively the "Software"), free of charge and under any and all
+copyright rights in the Software, and any and all patent rights owned or
+freely licensable by each licensor hereunder covering either (i) the
+unmodified Software as contributed to or provided by such licensor, or (ii)
+the Larger Works (as defined below), to deal in both
+
+(a) the Software, and
+
+(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+one is included with the Software each a "Larger Work" to which the Software
+is contributed by such licensors),
+
+without restriction, including without limitation the rights to copy, create
+derivative works of, display, perform, and distribute the Software and make,
+use, sell, offer for sale, import, export, have made, and have sold the
+Software and the Larger Work(s), and to sublicense the foregoing rights on
+either these or other terms.
+
+This license is subject to the following condition:
+
+The above copyright notice and either this complete permission notice or at a
+minimum a reference to the UPL must be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/distribution/proxy/src/main/release-docs/LICENSE b/distribution/proxy/src/main/release-docs/LICENSE
index 37e07a7e84a..a099c99cec9 100644
--- a/distribution/proxy/src/main/release-docs/LICENSE
+++ b/distribution/proxy/src/main/release-docs/LICENSE
@@ -360,3 +360,12 @@ The text of each license is also included at licenses/LICENSE-[project].txt.
     jul-to-slf4j 1.7.36: https://www.slf4j.org, MIT
     slf4j-api 1.7.36: https://www.slf4j.org, MIT
     jnanoid 2.0.0: https://github.com/aventrix/jnanoid, MIT 
+
+========================================================================
+UPL licenses
+========================================================================
+
+The following components are provided under the UPL License. See project link for details.
+The text of each license is also included at licenses/LICENSE-[project].txt.
+
+    truffle-api 21.2.0: http://www.graalvm.org/, UPL
diff --git a/distribution/proxy/src/main/release-docs/licenses/LICENSE-truffle-api.txt b/distribution/proxy/src/main/release-docs/licenses/LICENSE-truffle-api.txt
new file mode 100644
index 00000000000..d656a31cb15
--- /dev/null
+++ b/distribution/proxy/src/main/release-docs/licenses/LICENSE-truffle-api.txt
@@ -0,0 +1,35 @@
+The Universal Permissive License (UPL), Version 1.0
+
+Subject to the condition set forth below, permission is hereby granted to any
+person obtaining a copy of this software, associated documentation and/or
+data (collectively the "Software"), free of charge and under any and all
+copyright rights in the Software, and any and all patent rights owned or
+freely licensable by each licensor hereunder covering either (i) the
+unmodified Software as contributed to or provided by such licensor, or (ii)
+the Larger Works (as defined below), to deal in both
+
+(a) the Software, and
+
+(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+one is included with the Software each a "Larger Work" to which the Software
+is contributed by such licensors),
+
+without restriction, including without limitation the rights to copy, create
+derivative works of, display, perform, and distribute the Software and make,
+use, sell, offer for sale, import, export, have made, and have sold the
+Software and the Larger Work(s), and to sublicense the foregoing rights on
+either these or other terms.
+
+This license is subject to the following condition:
+
+The above copyright notice and either this complete permission notice or at a
+minimum a reference to the UPL must be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md
index 8e523158383..90005df99b5 100644
--- a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md
+++ b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md
@@ -21,7 +21,7 @@ services:
   apache-shardingsphere-proxy-native:
     image: ghcr.io/apache/shardingsphere-proxy-native:latest
     volumes:
-      - ./custom/conf:/conf
+      - ./custom/conf:/opt/shardingsphere-proxy-native/conf
     ports:
       - "3307:3307"
 ```
@@ -34,17 +34,29 @@ services:
   需要等待 Junit 5 Platform 的集成,你总是需要在构建 GraalVM Native Image 的过程中,
   加上特定于 `GraalVM Native Build Tools` 的 `-DskipNativeTests` 或 `-DskipTests` 参数跳过 Native Image 中的单元测试。
 
+- 如下 3 个算法类由于涉及到 GraalVM Truffle Espresso 不方便在 host JVM 和 guest JVM 之间交互的 `groovy.lang.Closure`
+  类,暂未可在 GraalVM Native Image 下使用。
+    - `org.apache.shardingsphere.sharding.algorithm.sharding.complex.ComplexInlineShardingAlgorithm`
+    - `org.apache.shardingsphere.sharding.algorithm.sharding.hint.HintInlineShardingAlgorithm`
+    - `org.apache.shardingsphere.sharding.algorithm.sharding.inline.InlineShardingAlgorithm`
+
+- 当前阶段,GraalVM Native Image 形态的 ShardingSphere Proxy 处于混合 AOT ( GraalVM Native Image ) 和 JIT ( GraalVM
+  Truffle Espresso ) 运行的阶段。由于 https://github.com/oracle/graal/issues/4555 尚未关闭,GraalVM Truffle Espresso
+  运行需要的 `.so` 文件并不会进入 GraalVM Native Image 内。因此如果你需要在 Docker Image 外运行 ShardingSphere Proxy
+  Native 的二进制文件,你需要确保系统环境变量 `GRAALVM_HOME` 或 `JAVA_HOME` 指向 GraalVM 的 `bin` 目录,并且此 GraalVM
+  实例已经通过 `GraalVM Updater` 安装了 `espresso` 组件。目前,`GRAALVM_HOME` 优先级比 `JAVA_HOME` 高。
+
 - 本节假定处于 Linux(amd64,aarch64), MacOS(amd64)或 Windows(amd64)环境。
-  如果你位于 MacOS(aarch64/M1) 环境,你需要关注尚未关闭的 https://github.com/oracle/graal/issues/2666。
+  如果你位于 MacOS(aarch64/M1) 环境,你需要关注尚未关闭的 https://github.com/oracle/graal/issues/2666 。
 
 ## 前提条件
 
 1. 根据 https://www.graalvm.org/downloads/ 要求安装和配置 JDK 17 对应的 `GraalVM CE` 或 `GraalVM EE`。
    同时可以通过 `SDKMAN!` 安装 JDK 17 对应的 `GraalVM CE`。
 
-2. 通过 `GraalVM Updater` 工具安装 `native-image` 组件。
+2. 通过 `GraalVM Updater` 工具安装 `native-image` 和 `espresso` 组件。
 
-3. 根据 https://www.graalvm.org/22.2/reference-manual/native-image/#prerequisites 的要求安装本地工具链。
+3. 根据 https://www.graalvm.org/22.3/reference-manual/native-image/#prerequisites 的要求安装本地工具链。
 
 4. 如果需要构建 Docker Image, 确保 `docker-cli` 在系统环境变量内。
 
@@ -73,16 +85,16 @@ services:
 ```xml
 
 <dependencies>
-    <dependency>
-        <groupId>com.mysql</groupId>
-        <artifactId>mysql-connector-j</artifactId>
-        <version>8.0.31</version>
-    </dependency>
-    <dependency>
-        <groupId>org.apache.shardingsphere</groupId>
-        <artifactId>shardingsphere-sql-translator-jooq-provider</artifactId>
-        <version>5.2.0</version>
-    </dependency>
+  <dependency>
+    <groupId>com.mysql</groupId>
+    <artifactId>mysql-connector-j</artifactId>
+    <version>8.0.32</version>
+  </dependency>
+  <dependency>
+    <groupId>org.apache.shardingsphere</groupId>
+    <artifactId>shardingsphere-sql-translator-jooq-provider</artifactId>
+    <version>5.3.1</version>
+  </dependency>
 </dependencies>
 ```
 
@@ -116,14 +128,14 @@ services:
   apache-shardingsphere-proxy-native:
     image: apache/shardingsphere-proxy-native:latest
     volumes:
-      - ./custom/conf:/conf
+      - ./custom/conf:/opt/shardingsphere-proxy-native/conf
     ports:
       - "3307:3307"
 ```
 
 - 如果你不对 Git Source 做任何更改, 上文提及的命令将使用 `oraclelinux:9-slim` 作为 Base Docker Image。
   但如果你希望使用 `busybox:glic`,`gcr.io/distroless/base` 或 `scratch` 等更小体积的 Docker Image 作为 Base Docker
-  Image,你需要根据 https://www.graalvm.org/22.2/reference-manual/native-image/guides/build-static-executables/ 的要求,
+  Image,你需要根据 https://www.graalvm.org/22.3/reference-manual/native-image/guides/build-static-executables/ 的要求,
   做为 `pom.xml`的 `native profile` 添加 `-H:+StaticExecutableWithDynamicLibC` 的 `jvmArgs` 等操作。
   另请注意,某些第三方依赖将需要在 `Dockerfile` 安装更多系统库,例如 `libdl`。
   因此请确保根据你的使用情况调整 `distribution/proxy-native`
@@ -135,7 +147,7 @@ services:
   Proxy,其提供的可观察性的能力与 https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-proxy/observability/
   并不一致。
 
-- 你可以使用 https://www.graalvm.org/22.2/tools/ 提供的一系列命令行工具或可视化工具观察 GraalVM Native Image
+- 你可以使用 https://www.graalvm.org/22.3/tools/ 提供的一系列命令行工具或可视化工具观察 GraalVM Native Image
   的内部行为,并根据其要求使用 VSCode 完成调试工作。
   如果你正在使用 IntelliJ IDEA 并且希望调试生成的 GraalVM Native Image,
   你可以关注 https://blog.jetbrains.com/idea/2022/06/intellij-idea-2022-2-eap-5/#Experimental_GraalVM_Native_Debugger_for_Java
diff --git a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md
index bf482eeb6f4..0f03b9d8834 100644
--- a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md
+++ b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md
@@ -23,7 +23,7 @@ services:
   apache-shardingsphere-proxy-native:
     image: ghcr.io/apache/shardingsphere-proxy-native:latest
     volumes:
-      - ./custom/conf:/conf
+      - ./custom/conf:/opt/shardingsphere-proxy-native/conf
     ports:
       - "3307:3307"
 ````
@@ -38,8 +38,23 @@ services:
   Plus `-DskipNativeTests` or `-DskipTests` parameter specific to `GraalVM Native Build Tools` to skip unit tests in
   Native Image.
 
+- The following three algorithm classes are not available under GraalVM Native Image because they involve
+  the `groovy.lang.Closure` class that is inconvenient for GraalVM Truffle Espresso to interact between the host JVM and
+  the guest JVM.
+    - `org.apache.shardingsphere.sharding.algorithm.sharding.complex.ComplexInlineShardingAlgorithm`
+    - `org.apache.shardingsphere.sharding.algorithm.sharding.hint.HintInlineShardingAlgorithm`
+    - `org.apache.shardingsphere.sharding.algorithm.sharding.inline.InlineShardingAlgorithm`
+
+- At the current stage, ShardingSphere Proxy in GraalVM Native Image is in the stage of mixed AOT ( GraalVM
+  Native Image ) and JIT ( GraalVM Truffle Espresso ) operation. Since https://github.com/oracle/graal/issues/4555 has
+  not been closed, the `.so` file required for GraalVM Truffle Espresso to run does not enter the GraalVM Native Image.
+  So if you need to run the binary files of ShardingSphere Proxy Native outside the Docker Image, you need to ensure
+  that the system environment variable `GRAALVM_HOME` or `JAVA_HOME` points to the `bin` directory of GraalVM, and this
+  GraalVM instance has been installed `espresso` component by `GraalVM Updater`. Currently, `GRAALVM_HOME` has higher
+  priority than `JAVA_HOME`.
+
 - This section assumes a Linux (amd64, aarch64), MacOS (amd64) or Windows (amd64) environment.
-  If you are on MacOS(aarch64/M1) environment, you need to follow https://github.com/oracle/graal/issues/2666 which is
+  If you are on MacOS (aarch64/M1) environment, you need to follow https://github.com/oracle/graal/issues/2666 which is
   not closed yet.
 
 ## Premise
@@ -47,9 +62,9 @@ services:
 1. Install and configure `GraalVM CE` or `GraalVM EE` for JDK 17 according to https://www.graalvm.org/downloads/.
    `GraalVM CE` for JDK 17 can also be installed via `SDKMAN!`.
 
-2. Install the `native-image` component via the `GraalVM Updater` tool.
+2. Install the `native-image` and `espresso` component via the `GraalVM Updater` tool.
 
-3. Install the local toolchain as required by https://www.graalvm.org/22.2/reference-manual/native-image/#prerequisites.
+3. Install the local toolchain as required by https://www.graalvm.org/22.3/reference-manual/native-image/#prerequisites.
 
 4. If you need to build a Docker Image, make sure `docker-cli` is in the system environment variables.
 
@@ -83,12 +98,12 @@ services:
     <dependency>
         <groupId>com.mysql</groupId>
         <artifactId>mysql-connector-j</artifactId>
-        <version>8.0.31</version>
+        <version>8.0.32</version>
     </dependency>
     <dependency>
         <groupId>org.apache.shardingsphere</groupId>
         <artifactId>shardingsphere-sql-translator-jooq-provider</artifactId>
-        <version>5.2.0</version>
+        <version>5.3.1</version>
     </dependency>
 </dependencies>
 ```
@@ -125,7 +140,7 @@ services:
   apache-shardingsphere-proxy-native:
     image: apache/shardingsphere-proxy-native:latest
     volumes:
-      - ./custom/conf:/conf
+      - ./custom/conf:/opt/shardingsphere-proxy-native/conf
     ports:
       - "3307:3307"
 ```
@@ -134,7 +149,7 @@ services:
   Base Docker Image.
   But if you want to use a smaller Docker Image like `busybox:glic`, `gcr.io/distroless/base` or `scratch` as the Base
   Docker Image, you need according
-  to https://www.graalvm.org/22.2/reference-manual/native-image/guides/build-static-executables/,
+  to https://www.graalvm.org/22.3/reference-manual/native-image/guides/build-static-executables/,
   Add operations such as `-H:+StaticExecutableWithDynamicLibC` to `jvmArgs` as the `native profile` of `pom.xml`.
   Also note that some 3rd party dependencies will require more system libraries such as `libdl` to be installed in
   the `Dockerfile`.
@@ -148,7 +163,7 @@ services:
   Not consistent.
 
 - You can observe GraalVM Native Image using a series of command line tools or visualization tools available
-  at https://www.graalvm.org/22.2/tools/, and use VSCode to debug it according to its requirements.
+  at https://www.graalvm.org/22.3/tools/, and use VSCode to debug it according to its requirements.
   If you are using IntelliJ IDEA and want to debug the generated GraalVM Native Image,
   You can
   follow https://blog.jetbrains.com/idea/2022/06/intellij-idea-2022-2-eap-5/#Experimental_GraalVM_Native_Debugger_for_Java
diff --git a/infra/pom.xml b/infra/pom.xml
index 3ae2d171c02..bc49370479a 100644
--- a/infra/pom.xml
+++ b/infra/pom.xml
@@ -38,5 +38,6 @@
         <module>executor</module>
         <module>merge</module>
         <module>context</module>
+        <module>util-groovy</module>
     </modules>
 </project>
diff --git a/infra/util/pom.xml b/infra/util-groovy/pom.xml
similarity index 79%
copy from infra/util/pom.xml
copy to infra/util-groovy/pom.xml
index aec174fd596..6ddcfb9df74 100644
--- a/infra/util/pom.xml
+++ b/infra/util-groovy/pom.xml
@@ -24,23 +24,17 @@
         <artifactId>shardingsphere-infra</artifactId>
         <version>5.3.2-SNAPSHOT</version>
     </parent>
-    <artifactId>shardingsphere-infra-util</artifactId>
+    
+    <artifactId>shardingsphere-infra-util-groovy</artifactId>
     
     <dependencies>
-        <dependency>
-            <groupId>org.apache.shardingsphere</groupId>
-            <artifactId>shardingsphere-test-util</artifactId>
-            <version>${project.version}</version>
-            <scope>test</scope>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.yaml</groupId>
-            <artifactId>snakeyaml</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.apache.groovy</groupId>
             <artifactId>groovy</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
     </dependencies>
 </project>
diff --git a/infra/util/src/main/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParser.java b/infra/util-groovy/src/main/java/org/apache/shardingsphere/infra/util/groovy/expr/HotspotInlineExpressionParser.java
similarity index 98%
copy from infra/util/src/main/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParser.java
copy to infra/util-groovy/src/main/java/org/apache/shardingsphere/infra/util/groovy/expr/HotspotInlineExpressionParser.java
index f57969908ab..caacaf5c691 100644
--- a/infra/util/src/main/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParser.java
+++ b/infra/util-groovy/src/main/java/org/apache/shardingsphere/infra/util/groovy/expr/HotspotInlineExpressionParser.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.util.expr;
+package org.apache.shardingsphere.infra.util.groovy.expr;
 
 import com.google.common.base.Strings;
 import com.google.common.collect.Sets;
@@ -39,7 +39,7 @@ import java.util.stream.Collectors;
  * Inline expression parser.
  */
 @RequiredArgsConstructor
-public final class InlineExpressionParser {
+public final class HotspotInlineExpressionParser {
     
     private static final char SPLITTER = ',';
     
diff --git a/infra/util/src/test/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParserTest.java b/infra/util-groovy/src/test/java/org/apache/shardingsphere/infra/util/groovy/expr/HotspotInlineExpressionParserTest.java
similarity index 67%
copy from infra/util/src/test/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParserTest.java
copy to infra/util-groovy/src/test/java/org/apache/shardingsphere/infra/util/groovy/expr/HotspotInlineExpressionParserTest.java
index 8b3de8a5378..3b60a857b7f 100644
--- a/infra/util/src/test/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParserTest.java
+++ b/infra/util-groovy/src/test/java/org/apache/shardingsphere/infra/util/groovy/expr/HotspotInlineExpressionParserTest.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.util.expr;
+package org.apache.shardingsphere.infra.util.groovy.expr;
 
 import org.junit.Test;
 
@@ -26,66 +26,66 @@ import static org.hamcrest.CoreMatchers.hasItems;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 
-public final class InlineExpressionParserTest {
+public final class HotspotInlineExpressionParserTest {
     
     @Test
     public void assertEvaluateForExpressionIsNull() {
-        List<String> expected = new InlineExpressionParser(null).splitAndEvaluate();
+        List<String> expected = new HotspotInlineExpressionParser(null).splitAndEvaluate();
         assertThat(expected, is(Collections.<String>emptyList()));
     }
     
     @Test
     public void assertEvaluateForSimpleString() {
-        List<String> expected = new InlineExpressionParser(" t_order_0, t_order_1 ").splitAndEvaluate();
+        List<String> expected = new HotspotInlineExpressionParser(" t_order_0, t_order_1 ").splitAndEvaluate();
         assertThat(expected.size(), is(2));
         assertThat(expected, hasItems("t_order_0", "t_order_1"));
     }
     
     @Test
     public void assertEvaluateForNull() {
-        List<String> expected = new InlineExpressionParser("t_order_${null}").splitAndEvaluate();
+        List<String> expected = new HotspotInlineExpressionParser("t_order_${null}").splitAndEvaluate();
         assertThat(expected.size(), is(1));
         assertThat(expected, hasItems("t_order_"));
     }
     
     @Test
     public void assertEvaluateForLiteral() {
-        List<String> expected = new InlineExpressionParser("t_order_${'xx'}").splitAndEvaluate();
+        List<String> expected = new HotspotInlineExpressionParser("t_order_${'xx'}").splitAndEvaluate();
         assertThat(expected.size(), is(1));
         assertThat(expected, hasItems("t_order_xx"));
     }
     
     @Test
     public void assertEvaluateForArray() {
-        List<String> expected = new InlineExpressionParser("t_order_${[0, 1, 2]},t_order_item_${[0, 2]}").splitAndEvaluate();
+        List<String> expected = new HotspotInlineExpressionParser("t_order_${[0, 1, 2]},t_order_item_${[0, 2]}").splitAndEvaluate();
         assertThat(expected.size(), is(5));
         assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2", "t_order_item_0", "t_order_item_2"));
     }
     
     @Test
     public void assertEvaluateForRange() {
-        List<String> expected = new InlineExpressionParser("t_order_${0..2},t_order_item_${0..1}").splitAndEvaluate();
+        List<String> expected = new HotspotInlineExpressionParser("t_order_${0..2},t_order_item_${0..1}").splitAndEvaluate();
         assertThat(expected.size(), is(5));
         assertThat(expected, hasItems("t_order_0", "t_order_1", "t_order_2", "t_order_item_0", "t_order_item_1"));
     }
     
     @Test
     public void assertEvaluateForComplex() {
-        List<String> expected = new InlineExpressionParser("t_${['new','old']}_order_${1..2}, t_config").splitAndEvaluate();
+        List<String> expected = new HotspotInlineExpressionParser("t_${['new','old']}_order_${1..2}, t_config").splitAndEvaluate();
         assertThat(expected.size(), is(5));
         assertThat(expected, hasItems("t_new_order_1", "t_new_order_2", "t_old_order_1", "t_old_order_2", "t_config"));
     }
     
     @Test
     public void assertEvaluateForCalculate() {
-        List<String> expected = new InlineExpressionParser("t_${[\"new${1+2}\",'old']}_order_${1..2}").splitAndEvaluate();
+        List<String> expected = new HotspotInlineExpressionParser("t_${[\"new${1+2}\",'old']}_order_${1..2}").splitAndEvaluate();
         assertThat(expected.size(), is(4));
         assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2", "t_old_order_1", "t_old_order_2"));
     }
     
     @Test
     public void assertEvaluateForExpressionPlaceHolder() {
-        List<String> expected = new InlineExpressionParser("t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}").splitAndEvaluate();
+        List<String> expected = new HotspotInlineExpressionParser("t_$->{[\"new$->{1+2}\",'old']}_order_$->{1..2}").splitAndEvaluate();
         assertThat(expected.size(), is(4));
         assertThat(expected, hasItems("t_new3_order_1", "t_new3_order_2", "t_old_order_1", "t_old_order_2"));
     }
@@ -102,19 +102,19 @@ public final class InlineExpressionParserTest {
                 expression.append(",");
             }
         }
-        List<String> expected = new InlineExpressionParser(expression.toString()).splitAndEvaluate();
+        List<String> expected = new HotspotInlineExpressionParser(expression.toString()).splitAndEvaluate();
         assertThat(expected.size(), is(1024));
         assertThat(expected, hasItems("ds_0.t_user_0", "ds_15.t_user_1023"));
     }
     
     @Test
     public void assertHandlePlaceHolder() {
-        assertThat(InlineExpressionParser.handlePlaceHolder("t_$->{[\"new$->{1+2}\"]}"), is("t_${[\"new${1+2}\"]}"));
-        assertThat(InlineExpressionParser.handlePlaceHolder("t_${[\"new$->{1+2}\"]}"), is("t_${[\"new${1+2}\"]}"));
+        assertThat(HotspotInlineExpressionParser.handlePlaceHolder("t_$->{[\"new$->{1+2}\"]}"), is("t_${[\"new${1+2}\"]}"));
+        assertThat(HotspotInlineExpressionParser.handlePlaceHolder("t_${[\"new$->{1+2}\"]}"), is("t_${[\"new${1+2}\"]}"));
     }
     
     @Test
     public void assertEvaluateClosure() {
-        assertThat(new InlineExpressionParser("${1+2}").evaluateClosure().call().toString(), is("3"));
+        assertThat(new HotspotInlineExpressionParser("${1+2}").evaluateClosure().call().toString(), is("3"));
     }
 }
diff --git a/infra/util/pom.xml b/infra/util/pom.xml
index aec174fd596..48d5927f65b 100644
--- a/infra/util/pom.xml
+++ b/infra/util/pom.xml
@@ -33,14 +33,67 @@
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-infra-util-groovy</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         
         <dependency>
             <groupId>org.yaml</groupId>
             <artifactId>snakeyaml</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.apache.groovy</groupId>
-            <artifactId>groovy</artifactId>
+            <groupId>org.graalvm.truffle</groupId>
+            <artifactId>truffle-api</artifactId>
         </dependency>
     </dependencies>
+    
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy</id>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <phase>process-test-classes</phase>
+                        <configuration>
+                            <artifactItems>
+                                <!--TODO Need to explore and change to `org.apache.shardingsphere:shardingsphere-infra-util-groovy:${project.version}`-->
+                                <artifactItem>
+                                    <groupId>org.apache.shardingsphere</groupId>
+                                    <artifactId>shardingsphere-infra-util</artifactId>
+                                    <version>5.3.1</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <destFileName>shardingsphere-infra-util.jar</destFileName>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.apache.groovy</groupId>
+                                    <artifactId>groovy</artifactId>
+                                    <version>${groovy.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <destFileName>groovy.jar</destFileName>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>com.google.guava</groupId>
+                                    <artifactId>guava</artifactId>
+                                    <version>${guava.version}</version>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <destFileName>guava.jar</destFileName>
+                                </artifactItem>
+                            </artifactItems>
+                            <outputDirectory>${project.build.outputDirectory}/espresso-need-libs</outputDirectory>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/infra/util/src/main/java/org/apache/shardingsphere/infra/util/expr/EspressoInlineExpressionParser.java b/infra/util/src/main/java/org/apache/shardingsphere/infra/util/expr/EspressoInlineExpressionParser.java
new file mode 100644
index 00000000000..bd111432969
--- /dev/null
+++ b/infra/util/src/main/java/org/apache/shardingsphere/infra/util/expr/EspressoInlineExpressionParser.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.infra.util.expr;
+
+import groovy.lang.Closure;
+import org.graalvm.polyglot.Context;
+import org.graalvm.polyglot.Value;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Espresso Inline expression parser.
+ */
+public class EspressoInlineExpressionParser {
+    
+    private static final Context POLYGLOT;
+    
+    private final Value espressoInlineExpressionParser;
+    
+    static {
+        // https://github.com/oracle/graal/issues/4555 not yet closed
+        String javaHome = System.getenv("GRAALVM_HOME");
+        if (javaHome == null) {
+            javaHome = System.getenv("JAVA_HOME");
+        }
+        if (javaHome == null) {
+            throw new RuntimeException("Failed to determine the system's environment variable GRAALVM_HOME or JAVA_HOME!");
+        }
+        System.setProperty("org.graalvm.home", javaHome);
+        URL resource = Thread.currentThread().getContextClassLoader().getResource("espresso-need-libs");
+        assert null != resource;
+        String dir = resource.getPath();
+        String javaClasspath = String.join(":", dir + "/groovy.jar", dir + "/guava.jar", dir + "/shardingsphere-infra-util.jar");
+        POLYGLOT = Context.newBuilder().allowAllAccess(true)
+                .option("java.MultiThreaded", "true")
+                .option("java.Classpath", javaClasspath)
+                .build();
+    }
+    
+    public EspressoInlineExpressionParser(final String inlineExpression) {
+        espressoInlineExpressionParser = POLYGLOT.getBindings("java")
+                .getMember("org.apache.shardingsphere.infra.util.expr.InlineExpressionParser")
+                .newInstance(inlineExpression);
+    }
+    
+    /**
+     * Replace all inline expression placeholders.
+     *
+     * @param inlineExpression inline expression with {@code $->}
+     * @return result inline expression with {@code $}
+     */
+    public static String handlePlaceHolder(final String inlineExpression) {
+        return POLYGLOT.getBindings("java")
+                .getMember("org.apache.shardingsphere.infra.util.expr.InlineExpressionParser")
+                .invokeMember("handlePlaceHolder", inlineExpression)
+                .as(String.class);
+    }
+    
+    /**
+     * Split and evaluate inline expression.
+     *
+     * @return result list
+     */
+    @SuppressWarnings("unchecked")
+    public List<String> splitAndEvaluate() {
+        List<String> splitAndEvaluate = espressoInlineExpressionParser.invokeMember("splitAndEvaluate").as(List.class);
+        // GraalVM Truffle Espresso CE 22.3.1 has a different behavior for generic List than Hotspot.
+        return splitAndEvaluate.size() == 0 ? Collections.emptyList() : splitAndEvaluate;
+    }
+    
+    /**
+     * Evaluate closure.
+     *
+     * @return closure
+     */
+    public Closure<?> evaluateClosure() {
+        return espressoInlineExpressionParser.invokeMember("evaluateClosure").as(Closure.class);
+    }
+}
diff --git a/infra/util/src/main/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParser.java b/infra/util/src/main/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParser.java
index f57969908ab..516d61eb53e 100644
--- a/infra/util/src/main/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParser.java
+++ b/infra/util/src/main/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParser.java
@@ -17,23 +17,11 @@
 
 package org.apache.shardingsphere.infra.util.expr;
 
-import com.google.common.base.Strings;
-import com.google.common.collect.Sets;
 import groovy.lang.Closure;
-import groovy.lang.GString;
-import groovy.lang.GroovyShell;
-import groovy.lang.Script;
 import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.util.groovy.expr.HotspotInlineExpressionParser;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
 
 /**
  * Inline expression parser.
@@ -41,22 +29,39 @@ import java.util.stream.Collectors;
 @RequiredArgsConstructor
 public final class InlineExpressionParser {
     
-    private static final char SPLITTER = ',';
+    private static final boolean IS_SUBSTRATE_VM;
     
-    private static final Map<String, Script> SCRIPTS = new ConcurrentHashMap<>();
+    private final EspressoInlineExpressionParser espressoInlineExpressionParser;
     
-    private static final GroovyShell SHELL = new GroovyShell();
+    private final HotspotInlineExpressionParser hotspotInlineExpressionParser;
     
-    private final String inlineExpression;
+    static {
+        // workaround for https://github.com/helidon-io/helidon-build-tools/issues/858
+        IS_SUBSTRATE_VM = System.getProperty("java.vm.name").equals("Substrate VM");
+    }
+    
+    public InlineExpressionParser(final String inlineExpression) {
+        if (IS_SUBSTRATE_VM) {
+            this.hotspotInlineExpressionParser = null;
+            this.espressoInlineExpressionParser = new EspressoInlineExpressionParser(inlineExpression);
+        } else {
+            this.hotspotInlineExpressionParser = new HotspotInlineExpressionParser(inlineExpression);
+            this.espressoInlineExpressionParser = null;
+        }
+    }
     
     /**
      * Replace all inline expression placeholders.
-     * 
+     *
      * @param inlineExpression inline expression with {@code $->}
      * @return result inline expression with {@code $}
      */
     public static String handlePlaceHolder(final String inlineExpression) {
-        return inlineExpression.contains("$->{") ? inlineExpression.replaceAll("\\$->\\{", "\\$\\{") : inlineExpression;
+        if (IS_SUBSTRATE_VM) {
+            return EspressoInlineExpressionParser.handlePlaceHolder(inlineExpression);
+        } else {
+            return HotspotInlineExpressionParser.handlePlaceHolder(inlineExpression);
+        }
     }
     
     /**
@@ -65,7 +70,13 @@ public final class InlineExpressionParser {
      * @return result list
      */
     public List<String> splitAndEvaluate() {
-        return Strings.isNullOrEmpty(inlineExpression) ? Collections.emptyList() : flatten(evaluate(split()));
+        if (IS_SUBSTRATE_VM) {
+            assert null != espressoInlineExpressionParser;
+            return espressoInlineExpressionParser.splitAndEvaluate();
+        } else {
+            assert null != hotspotInlineExpressionParser;
+            return hotspotInlineExpressionParser.splitAndEvaluate();
+        }
     }
     
     /**
@@ -74,121 +85,12 @@ public final class InlineExpressionParser {
      * @return closure
      */
     public Closure<?> evaluateClosure() {
-        return (Closure<?>) evaluate("{it -> \"" + inlineExpression + "\"}");
-    }
-    
-    private List<Object> evaluate(final List<String> inlineExpressions) {
-        List<Object> result = new ArrayList<>(inlineExpressions.size());
-        for (String each : inlineExpressions) {
-            StringBuilder expression = new StringBuilder(handlePlaceHolder(each));
-            if (!each.startsWith("\"")) {
-                expression.insert(0, "\"");
-            }
-            if (!each.endsWith("\"")) {
-                expression.append("\"");
-            }
-            result.add(evaluate(expression.toString()));
-        }
-        return result;
-    }
-    
-    private Object evaluate(final String expression) {
-        Script script;
-        if (SCRIPTS.containsKey(expression)) {
-            script = SCRIPTS.get(expression);
+        if (IS_SUBSTRATE_VM) {
+            assert null != espressoInlineExpressionParser;
+            return espressoInlineExpressionParser.evaluateClosure();
         } else {
-            script = SHELL.parse(expression);
-            SCRIPTS.put(expression, script);
-        }
-        return script.run();
-    }
-    
-    private List<String> split() {
-        List<String> result = new ArrayList<>();
-        StringBuilder segment = new StringBuilder();
-        int bracketsDepth = 0;
-        for (int i = 0; i < inlineExpression.length(); i++) {
-            char each = inlineExpression.charAt(i);
-            switch (each) {
-                case SPLITTER:
-                    if (bracketsDepth > 0) {
-                        segment.append(each);
-                    } else {
-                        result.add(segment.toString().trim());
-                        segment.setLength(0);
-                    }
-                    break;
-                case '$':
-                    if ('{' == inlineExpression.charAt(i + 1)) {
-                        bracketsDepth++;
-                    }
-                    if ("->{".equals(inlineExpression.substring(i + 1, i + 4))) {
-                        bracketsDepth++;
-                    }
-                    segment.append(each);
-                    break;
-                case '}':
-                    if (bracketsDepth > 0) {
-                        bracketsDepth--;
-                    }
-                    segment.append(each);
-                    break;
-                default:
-                    segment.append(each);
-                    break;
-            }
-        }
-        if (segment.length() > 0) {
-            result.add(segment.toString().trim());
-        }
-        return result;
-    }
-    
-    private List<String> flatten(final List<Object> segments) {
-        List<String> result = new ArrayList<>();
-        for (Object each : segments) {
-            if (each instanceof GString) {
-                result.addAll(assemblyCartesianSegments((GString) each));
-            } else {
-                result.add(each.toString());
-            }
-        }
-        return result;
-    }
-    
-    private List<String> assemblyCartesianSegments(final GString segment) {
-        Set<List<String>> cartesianValues = getCartesianValues(segment);
-        List<String> result = new ArrayList<>(cartesianValues.size());
-        for (List<String> each : cartesianValues) {
-            result.add(assemblySegment(each, segment));
-        }
-        return result;
-    }
-    
-    @SuppressWarnings("unchecked")
-    private Set<List<String>> getCartesianValues(final GString segment) {
-        List<Set<String>> result = new ArrayList<>(segment.getValues().length);
-        for (Object each : segment.getValues()) {
-            if (null == each) {
-                continue;
-            }
-            if (each instanceof Collection) {
-                result.add(((Collection<Object>) each).stream().map(Object::toString).collect(Collectors.toCollection(LinkedHashSet::new)));
-            } else {
-                result.add(Sets.newHashSet(each.toString()));
-            }
-        }
-        return Sets.cartesianProduct(result);
-    }
-    
-    private String assemblySegment(final List<String> cartesianValue, final GString segment) {
-        StringBuilder result = new StringBuilder();
-        for (int i = 0; i < segment.getStrings().length; i++) {
-            result.append(segment.getStrings()[i]);
-            if (i < cartesianValue.size()) {
-                result.append(cartesianValue.get(i));
-            }
+            assert null != hotspotInlineExpressionParser;
+            return hotspotInlineExpressionParser.evaluateClosure();
         }
-        return result.toString();
     }
 }
diff --git a/infra/util/src/test/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParserTest.java b/infra/util/src/test/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParserTest.java
index 8b3de8a5378..57d13f1d38e 100644
--- a/infra/util/src/test/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParserTest.java
+++ b/infra/util/src/test/java/org/apache/shardingsphere/infra/util/expr/InlineExpressionParserTest.java
@@ -113,8 +113,16 @@ public final class InlineExpressionParserTest {
         assertThat(InlineExpressionParser.handlePlaceHolder("t_${[\"new$->{1+2}\"]}"), is("t_${[\"new${1+2}\"]}"));
     }
     
+    /**
+     * TODO
+     * This method needs to avoid returning a groovy.lang.Closure class instance,
+     * and instead return the result of `Closure#call`.
+     * Because `org.graalvm.polyglot.Value#as` does not allow this type to be returned from the guest JVM.
+     */
     @Test
     public void assertEvaluateClosure() {
-        assertThat(new InlineExpressionParser("${1+2}").evaluateClosure().call().toString(), is("3"));
+        if (!System.getProperty("java.vm.name").equals("Substrate VM")) {
+            assertThat(new InlineExpressionParser("${1+2}").evaluateClosure().call().toString(), is("3"));
+        }
     }
 }
diff --git a/pom.xml b/pom.xml
index 10e846322e4..d42764f9e68 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,7 +76,8 @@
         <jaxb.version>2.3.0</jaxb.version>
         <annotation-api.version>1.3.2</annotation-api.version>
         <activation-api.version>1.2.0</activation-api.version>
-        
+        <truffle-api.version>21.2.0</truffle-api.version>
+
         <calcite.version>1.32.0</calcite.version>
         <netty.version>4.1.86.Final</netty.version>
         
@@ -128,7 +129,8 @@
         <maven-project-info-reports-plugin.version>2.8</maven-project-info-reports-plugin.version>
         <maven-plugin-plugin.version>3.4</maven-plugin-plugin.version>
         <maven-jxr-plugin.version>2.5</maven-jxr-plugin.version>
-        
+        <maven-dependency-plugin.version>2.10</maven-dependency-plugin.version>
+
         <lifecycle-mapping.version>1.0.0</lifecycle-mapping.version>
         <coveralls-maven-plugin.version>4.3.0</coveralls-maven-plugin.version>
         <cobertura-maven-plugin.version>2.7</cobertura-maven-plugin.version>
@@ -580,6 +582,12 @@
                 <version>${awaitility.version}</version>
                 <scope>test</scope>
             </dependency>
+
+            <dependency>
+                <groupId>org.graalvm.truffle</groupId>
+                <artifactId>truffle-api</artifactId>
+                <version>${truffle-api.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
     
@@ -850,6 +858,11 @@
                         </execution>
                     </executions>
                 </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-dependency-plugin</artifactId>
+                    <version>${maven-dependency-plugin.version}</version>
+                </plugin>
             </plugins>
         </pluginManagement>
         <plugins>
@@ -1071,6 +1084,9 @@
                 <groupId>org.jacoco</groupId>
                 <artifactId>jacoco-maven-plugin</artifactId>
                 <version>${jacoco-maven-plugin.version}</version>
+                <configuration>
+                    <excludes>**/*.jar</excludes>
+                </configuration>
                 <executions>
                     <execution>
                         <goals>