Quarkus构建native-image遇到的问题及解决
本机构建 native-image
如果你本地安装了 Graal VM 的话,可以在项目目录下直接执行:
mvn clean package -Pnative
构建的时间比较长,构建完成后就会在 ./target
目录下生成一个二进制执行文件,一般名字是 quarkus-demo-1.0-runner
,直接执行这个二进制文件就可以运行项目了。
➜ target: ./quarkus-demo-1.0-runner
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2021-07-09 16:54:10,812 INFO [io.quarkus] (main) quarkus-demo 1.0 native (powered by Quarkus 2.0.1.Final) started in 0.121s. Listening on: http://0.0.0.0:8080
2021-07-09 16:54:11,041 INFO [io.quarkus] (main) Profile prod activated.
2021-07-09 16:54:11,041 INFO [io.quarkus] (main) Installed features: [cdi, resteasy, smallrye-context-propagation]
^C2021-07-09 16:55:12,904 INFO [io.quarkus] (Shutdown thread) quarkus-demo stopped in 0.008s
容器构建 native-image
如果你本地没有安装 Graal VM 的话,Quarkus 官方还提供了一个构建的基础镜像:quay.io/quarkus/ubi-quarkus-native-image
,我们可以直接执行以下命令进行构建:
mvn clean package -Pnative -Dquarkus.native.container-build=true
容器构建遇到的问题
1. 构建时内存不足
在使用容器构建 native-image 的时候,可以会报如下错误:
[ERROR] Failed to execute goal io.quarkus:quarkus-maven-plugin:2.0.1.Final:build (default) on project quarkus-demo: Failed to build quarkus application: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[ERROR] [error]: Build step io.quarkus.deployment.pkg.steps.NativeImageBuildStep#build threw an exception: java.lang.RuntimeException: Failed to build native image
[ERROR] at io.quarkus.deployment.pkg.steps.NativeImageBuildStep.build(NativeImageBuildStep.java:223)
[ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR] at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[ERROR] at io.quarkus.deployment.ExtensionLoader$2.execute(ExtensionLoader.java:820)
[ERROR] at io.quarkus.builder.BuildContext.run(BuildContext.java:277)
[ERROR] at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
[ERROR] at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2442)
[ERROR] at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1476)
[ERROR] at java.base/java.lang.Thread.run(Thread.java:829)
[ERROR] at org.jboss.threads.JBossThread.run(JBossThread.java:501)
[ERROR] Caused by: java.lang.RuntimeException: Image generation failed. Exit code was 137 which indicates an out of memory error. Consider increasing the Xmx value for native image generation by setting the "quarkus.native.native-image-xmx" property
[ERROR] at io.quarkus.deployment.pkg.steps.NativeImageBuildStep.imageGenerationFailed(NativeImageBuildStep.java:360)
[ERROR] at io.quarkus.deployment.pkg.steps.NativeImageBuildStep.build(NativeImageBuildStep.java:200)
[ERROR] ... 11 more
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
错误提示时内存不足,可以尝试设置 quarkus.native.native-image-xmx
参数,但是设置了这个参数还是报这个错。在查阅资料后,在一个 stackoverflow 的回答中看到了这样一句话:
Pay attention it has to be less than the memory you set in your docker daemon.
他说必须小于您在 docker 守护进程中设置的内存。
然后我查看 docker 的官方文档时发现,在 Mac 和 Windows 中默认的内存是 2GB。
所以只要调高这个值就可以了,推荐是 8GB,各系统设置方法:
Mac:https://docs.docker.com/docker-for-mac/#resources
Windows:https://docs.docker.com/docker-for-windows/#resources
2. 容器构建后的二进制文件无法运行
容器构建 native-image 完成后生成的二进制文件不能执行,提示 zsh: exec format error: ./quarkus-demo-1.0-runner
这是因为我本机是 Mac 系统,但是 Quarkus 提供的构建镜像是 Linux 系统,但是 Graal VM 目前好像并不支持交叉编译,所以在 Linux 系统里构建的二进制文件只能在 Linux 系统里执行。
所以我们可以直接用容器来运行这个构建好的二进制文件。