GraalVM 是一种高性能、多语言通用虚拟机和编译器技术。它由 Oracle 开发并开源,旨在为不同的编程语言和应用场景提供统一的运行时环境和编译器平台。以下是 GraalVM 的一些主要特点和功能:
GraalVM 在加速 Java 应用程序、支持多语言开发、优化资源使用等方面提供了一系列创新功能。它被广泛用于构建高性能的应用程序、微服务、嵌入式系统以及各种语言的运行时环境。
注意:
https://www.graalvm.org/downloads/
将JAVA_HOME配置到该层目录下
并将JAVA_HOME的/bin添加到PATH中。(不用管这里的jre/bin,我只是偷懒不想换)
打开命令行,输入以下命令,看是否配置环境变量成功
https://visualstudio.microsoft.com/zh-hans/
打开Visual Studio Installer,选择使用C++的桌面开发,并如图选择组件。
添加以下三个环境变量
INCLUDE=C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\shared;D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.16.27023\include.;
LIB=C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17134.0\um\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17134.0\ucrt\x64;D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.16.27023\lib\x64;
PATH=%PATH%;D:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.16.27023\bin\HostX64\x64
由于GraalVM对于反射的支持不是很好,所以要为JNI的操作类写配置文件。在项目中创建jniconfig
,该文件是json格式的文件,用来描述JNI数据交换类的。你的JNI程序是用哪个类交换数据,那你就需要为这个类编写这个配置文件,否则GraalVM的本地镜像不能正常运行。示例如下图,fields
是属性,methods
是方法,name
是路径变量名。
[
{
"name" : "com.cInterface.Data",
"queryAllDeclaredConstructors" : true,
"queryAllPublicConstructors" : true,
"queryAllDeclaredMethods" : true,
"queryAllPublicMethods" : true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name" : "com.cInterface.Data",
"fields" : [
{ "name" : "mParam" },
{ "name" : "mInfo" }
],
"methods" : [
{ "name" : "<init>", "parameterTypes" : [] },
{ "name" : "getParam", "parameterTypes" : [] },
{ "name" : "setInfo", "parameterTypes" : ["byte[]", "int"] }
]
}
]
注意:你需要知道你引入的项目依赖是否支持GraalVM,否则可能会出现不可预知的问题。
在pom.xml你主要做的事情是
pom.xml附在文章的最后面
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<!-- imageName用于设置生成的二进制文件名称 -->
<imageName>${project.artifactId}</imageName>
<!-- mainClass用于指定main方法类路径 -->
<mainClass>com.xxx.Application</mainClass>
<buildArgs>
<!-- 这些配置类基本都是指定初始化时间和一些配置,都不用管,并且不要动,否则可能会打包失败 -->
--no-fallback
--initialize-at-build-time=org.springframework.util.unit.DataSize
--initialize-at-build-time=org.slf4j.MDC
--initialize-at-build-time=ch.qos.logback.classic.Level
--initialize-at-build-time=ch.qos.logback.classic.Logger
--initialize-at-build-time=ch.qos.logback.core.util.StatusPrinter
--initialize-at-build-time=ch.qos.logback.core.status.StatusBase
--initialize-at-build-time=ch.qos.logback.core.status.InfoStatus
--initialize-at-build-time=ch.qos.logback.core.spi.AppenderAttachableImpl
--initialize-at-build-time=org.slf4j.LoggerFactory
--initialize-at-build-time=ch.qos.logback.core.util.Loader
--initialize-at-build-time=org.slf4j.impl.StaticLoggerBinder
--initialize-at-build-time=ch.qos.logback.classic.spi.ThrowableProxy
--initialize-at-build-time=ch.qos.logback.core.CoreConstants
--report-unsupported-elements-at-runtime
--allow-incomplete-classpath
-H:+ReportExceptionStackTraces
<!-- 指定刚刚编写的jniconfig路径,我这里比较懒,就直接放在pom.xml相同路径下 -->
-H:JNIConfigurationFiles=jniconfig
</buildArgs>
</configuration>
</plugin>
打开命令行工具,注意是打开这个,不是cmd或者powershell。因为cmd和powershell有命令长度限制,必须使用这个进行命令行操作。
cd到项目的pom.xml文件夹下,输入以下命令进行打包。-Pnative
是指定打包成本地镜像,-DskipTests
是跳过测试。
mvn -Pnative -DskipTests native:compile
稍等一会,看到以下信息即为打包成功。
打包完成后,项目根路径会有一个target文件夹,里面有个exe文件和awt.dll、java.dll、jwm.dll文件。这就是项目运行的全部文件了。
注意:若你的项目为JNI项目,请把你预先编译好的dll文件放到exe同路径下,或放到
java.library.path
路径上,否则项目无法正常运行。
GraalVM 的本地镜像打包功能可以将 Java 应用程序及其依赖项打包成本地可执行文件,无需依赖 JVM,从而带来许多好处:
GraalVM 的本地镜像打包功能为 Java 应用程序提供了更快的启动时间、更低的内存占用、更轻量级的分发文件等优势,适用于多种场景,特别是对于需要快速启动和优化资源的应用程序。
pom.xml文件
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.2</version>
<relativePath />
</parent>
<groupId>com.xxx</groupId>
<artifactId>application</artifactId>
<version>1.0.1-SNAPSHOT</version>
<name>Application</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- springboot-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<!-- imageName用于设置生成的二进制文件名称 -->
<imageName>${project.artifactId}</imageName>
<!-- mainClass用于指定main方法类路径 -->
<mainClass>com.xxx.Application</mainClass>
<buildArgs>
--no-fallback
--initialize-at-build-time=org.springframework.util.unit.DataSize
--initialize-at-build-time=org.slf4j.MDC
--initialize-at-build-time=ch.qos.logback.classic.Level
--initialize-at-build-time=ch.qos.logback.classic.Logger
--initialize-at-build-time=ch.qos.logback.core.util.StatusPrinter
--initialize-at-build-time=ch.qos.logback.core.status.StatusBase
--initialize-at-build-time=ch.qos.logback.core.status.InfoStatus
--initialize-at-build-time=ch.qos.logback.core.spi.AppenderAttachableImpl
--initialize-at-build-time=org.slf4j.LoggerFactory
--initialize-at-build-time=ch.qos.logback.core.util.Loader
--initialize-at-build-time=org.slf4j.impl.StaticLoggerBinder
--initialize-at-build-time=ch.qos.logback.classic.spi.ThrowableProxy
--initialize-at-build-time=ch.qos.logback.core.CoreConstants
--report-unsupported-elements-at-runtime
--allow-incomplete-classpath
-H:+ReportExceptionStackTraces
-H:JNIConfigurationFiles=jniconfig
</buildArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
手机扫一扫
移动阅读更方便
你可能感兴趣的文章