Spring + GraalVM运行跟踪代理后仍然抛出新方法找不到异常。

huangapple go评论62阅读模式
英文:

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()

我认为问题可能是反射调用的提示未被正确收集,或者它们没有进入本机映像工具正确的位置以供其提取,但我已经没有尝试的想法了,所以我感激任何指导。

版本:

复现步骤

这是我正在进行实验的演示项目。详情请参阅自述文件,并由项目根目录中的脚本触发步骤和训练。

  1. 运行Spring Boot本机构建以创建初始提示和类,否则跟踪代理将不会启动。(真的很好地消除这种开销)
mvn clean package -DskipTests -Pnative
  1. 将生成的提示+类打包到jar中的META-INF目录下。
mvn package -DskipTests
  1. 启动跟踪代理以附加现有提示。
"$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"
  1. 调用服务端点以使每个内部方法调用对跟踪代理可见。
  2. 停止跟踪代理。
  3. 将生成的提示+类打包到jar中的META-INF目录下。
  4. 解压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
  1. 运行本机映像构建工具
"$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:

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.

  1. 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
  1. Package the generated hints + classes under META-INF into the jar.
mvn package -DskipTests
  1. 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"
  1. Call the service endpoint to make every internal method call visible for the tracing agent.
  2. Stop the tracing agent.
  3. Package the generated hints + classes under META-INF into the jar.
  4. 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
  1. 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"}

服务器端日志如下:

Spring + GraalVM运行跟踪代理后仍然抛出新方法找不到异常。

英文:

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"}

and server side logs
Spring + GraalVM运行跟踪代理后仍然抛出新方法找不到异常。

huangapple
  • 本文由 发表于 2023年5月30日 07:49:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76360865.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定