英文:
Spring + GraalVM throws new method found exception even after running the tracing agent
问题
UPDATE: 请查看答案,以了解正确(并且简单得多)的训练和构建本机映像步骤。
我一直在尝试创建Spring Boot本机
构建步骤,不手动添加任何配置
,完全依赖GraalVM跟踪代理
来发现一切。
它运行得很好,直到我在服务层中“隐藏”了一个依赖反射的手动Jackson ObjectMapper调用。
然后,GraalVM的native-image
构建的图像创建步骤会中断,并抱怨“隐藏”的方法,本应该被跟踪代理发现的(请参见下面的步骤3-5)。
[7/7] Creating image... (0.0s @ 3.14GB)
Fatal error: com.oracle.svm.core.util.VMError$HostedError: com.oracle.svm.core.util.VMError$HostedError: New Method or Constructor found as reachable after static analysis: public java.lang.String com.tlvlp.springnativedemo.AppendRequest.appendWith()
我认为问题可能是反射调用的提示未被正确收集,或者它们没有进入本机映像工具正确的位置以供其提取,但我已经没有尝试的想法了,所以我感激任何指导。
版本:
Java 17
GraalVM 22.3.r17
Spring Boot 3.1.0
(应该已经包含对早期报告的类似问题的修复)。
复现步骤
这是我正在进行实验的演示项目。详情请参阅自述文件,并由项目根目录中的脚本触发步骤和训练。
- 运行Spring Boot本机构建以创建初始提示和类,否则跟踪代理将不会启动。(真的很好地消除这种开销)
mvn clean package -DskipTests -Pnative
- 将生成的提示+类打包到jar中的
META-INF
目录下。
mvn package -DskipTests
- 启动跟踪代理以附加现有提示。
"$GRAALVM_HOME"/bin/java \
-Dspring.aot.enabled=true \
-agentlib:native-image-agent=config-merge-dir="$(pwd)"/target/classes/META-INF/native-image \
-jar "$INPUT_JAR_PATH"
- 调用服务端点以使每个内部方法调用对跟踪代理可见。
- 停止跟踪代理。
- 将生成的提示+类打包到jar中的
META-INF
目录下。 - 解压jar到单独的文件夹中(如Spring Boot本机指南中建议的)
rm -rf "$NATIVE_BUILD_DIR"
mkdir -p "$NATIVE_BUILD_DIR"
cd "$NATIVE_BUILD_DIR" || exit 1
jar -xvf $INPUT_JAR_WITH_NATIVE_HINTS
- 运行本机映像构建工具
"$GRAALVM_HOME"/bin/native-image \
--no-fallback \
-H:Name=$OUTPUT_EXECUTABLE_NAME \
-cp .:BOOT-INF/classes:`find BOOT-INF/lib | tr '\n' ':'` || exit 1
英文:
> UPDATE: See the answer for the correct (and much simpler) steps to train and build the native image.
I've been trying to create Spring Boot native
build steps without manually adding any configuration
, relying entirely on the GraalVM Tracing Agent
to discover everything.
It works fine, until I "hide" a manual Jackson ObjectMapper call in the service layer, that relies on reflection.
Then the GraalVM native-image
build's image creation step breaks and complains about the "hidden" method, that should have been discovered by the tracing agent (see steps 3-5 below).
[7/7] Creating image... (0.0s @ 3.14GB)
Fatal error: com.oracle.svm.core.util.VMError$HostedError: com.oracle.svm.core.util.VMError$HostedError: New Method or Constructor found as reachable after static analysis: public java.lang.String com.tlvlp.springnativedemo.AppendRequest.appendWith()
I think the problem might be that either the hints for the reflection call are somehow not collected or they don't end up in the right place for the native-image tool to pick it up, but I have run out of ideas to try so I appreciate any guidance.
Versions:
Java 17
GraalVM 22.3.r17
Spring Boot 3.1.0
(should already contain fixes for a similar issue reported earlier).
Steps to reproduce
This is the demo project that I was experimenting on. Details are in the README and there the steps + training are triggered by scripts in the project's root.
- Run a Spring Boot native build to create the initial hints & classes, otherwise the tracing agent will not start. (Would be really nice to eliminate this overhead)
mvn clean package -DskipTests -Pnative
- Package the generated hints + classes under
META-INF
into the jar.
mvn package -DskipTests
- Start the tracing agent to append the existing hints.
"$GRAALVM_HOME"/bin/java \
-Dspring.aot.enabled=true \
-agentlib:native-image-agent=config-merge-dir="$(pwd)"/target/classes/META-INF/native-image \
-jar "$INPUT_JAR_PATH"
- Call the service endpoint to make every internal method call visible for the tracing agent.
- Stop the tracing agent.
- Package the generated hints + classes under
META-INF
into the jar. - Unpack the jar to a separate folder (as advised in the Spring Boot native guide)
rm -rf "$NATIVE_BUILD_DIR"
mkdir -p "$NATIVE_BUILD_DIR"
cd "$NATIVE_BUILD_DIR" || exit 1
jar -xvf $INPUT_JAR_WITH_NATIVE_HINTS
- Run the native-image build tool
"$GRAALVM_HOME"/bin/native-image \
--no-fallback \
-H:Name=$OUTPUT_EXECUTABLE_NAME \
-cp .:BOOT-INF/classes:`find BOOT-INF/lib | tr '\n' ':'` || exit 1
答案1
得分: 1
这个错误与在AppendRequest
中使用"record"有关。如果你查看GitHub的问题,你会发现有时它在GraalVM上无法正常工作,但在我将它转换成以下类似的类之后,一切都按预期工作了。
package com.tlvlp.springnativedemo;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
@Data
public class AppendRequest {
@NotEmpty
String appendWith;
}
用于跟踪的命令如下:
java -agentlib:native-image-agent=config-output-dir=./src/main/resources/META-INF/native-image/ -jar target/native-test.jar
用于生成本地镜像的命令如下:
mvn -Pnative native:compile
用于调用服务的命令如下:
curl -X 'POST' 'http://localhost:8080/append' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{}'
响应如下:
{"appended":"START-null"}
服务器端日志如下:
英文:
That error is related using "record" for AppendRequest, if you check github issues you will see there were sometimes it was not working very friendly with graalvm, after I convert that to class like below everything worked as expected.
package com.tlvlp.springnativedemo;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
@Data
public class AppendRequest {
@NotEmpty
String appendWith;
}
for tracing I used command below
java -agentlib:native-image-agent=config-output-dir=./src/main/resources/META-INF/native-image/ -jar target/native-test.jar
for generating the native image used
mvn -Pnative native:compile
for calling the service
curl -X 'POST' 'http://localhost:8080/append' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{}'
response
{"appended":"START-null"}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论