fastjson2
fastjson2 copied to clipboard
[BUG]Spring Boot 3在GraalVM Native打包序列化异常
问题描述
在GraalVM CE情况下使用JSONPath获取出现一下一场
com.alibaba.fastjson2.JSONException: create instance error
环境信息
- OS信息: [e.g.:macOS13.4.1 (c) (22F770820d) 16 GB]
- JDK信息: [e.g.:GraalVM CE 17.0.7]
- 版本信息:[e.g.:Fastjson2 2.0.37]
重现步骤
- 调用方法
JSON.parseArray(data).toList(PD01.class);
- 输入参数
// 无
-
出现
com.alibaba.fastjson2.JSONException: create instance error
错误 -
复现代码
public class X {
public static void nativeTest() {
String data = "[{\"PD01A\":{\"PD01AD03\":2,\"PD01AD01\":1}}}]";
List<PD01> l = JSON.parseArray(data).toList(PD01.class);
}
public static void main(String[] args) {
nativeTest();
}
public static class PD01 {
private PD01A PD01A;
public PD01() {}
public PD01(PD01A PD01A) { this.PD01A = PD01A; }
public PD01A getPD01A() { return PD01A; }
public void setPD01A(PD01A PD01A) { this.PD01A = PD01A; }
}
public static class PD01A {
private String PD01AD01;
private String PD01AD03;
public PD01A() {}
public PD01A(String PD01AD01, String PD01AD03) {
this.PD01AD01 = PD01AD01;
this.PD01AD03 = PD01AD03;
}
public String getPD01AD01() { return PD01AD01; }
public void setPD01AD01(String PD01AD01) { this.PD01AD01 = PD01AD01; }
public String getPD01AD03() { return PD01AD03; }
public void setPD01AD03(String PD01AD03) { this.PD01AD03 = PD01AD03; }
}
}
期待的正确结果
能正确获得List<PD01>对象,并操作
相关日志输出
2023-07-27T15:57:34.115+08:00 ERROR 97705 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: com.alibaba.fastjson2.JSONException: create instance error, class com.example.test_a.ttt.PD01] with root cause
com.alibaba.fastjson2.JSONException: create instance error, class com.example.test_a.ttt.PD01
at com.alibaba.fastjson2.reader.ObjectReaderAdapter.createInstance0(ObjectReaderAdapter.java:333) ~[test_a:na]
at com.alibaba.fastjson2.reader.ObjectReaderAdapter.createInstance(ObjectReaderAdapter.java:382) ~[test_a:na]
at com.alibaba.fastjson2.reader.ObjectReaderBean.readObject(ObjectReaderBean.java:332) ~[test_a:na]
at com.alibaba.fastjson2.reader.ObjectReaderImplList.readObject(ObjectReaderImplList.java:570) ~[na:na]
at com.alibaba.fastjson2.JSONReader.readArray(JSONReader.java:2151) ~[test_a:na]
at com.alibaba.fastjson2.JSON.parseArray(JSON.java:2469) ~[na:na]
at com.example.test_a.TestAApplication.index(TestAApplication.java:58) ~[test_a:na]
at [email protected]/java.lang.reflect.Method.invoke(Method.java:568) ~[test_a:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207) ~[test_a:6.0.10]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152) ~[test_a:6.0.10]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[test_a:6.0.10]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884) ~[test_a:6.0.10]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[test_a:6.0.10]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[test_a:6.0.10]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081) ~[test_a:6.0.10]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974) ~[test_a:6.0.10]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011) ~[test_a:6.0.10]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903) ~[test_a:6.0.10]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564) ~[test_a:6.0]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[test_a:6.0.10]
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[test_a:6.0]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[na:na]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[test_a:10.1.10]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[na:na]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[test_a:6.0.10]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[test_a:6.0.10]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[na:na]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[test_a:6.0.10]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[test_a:6.0.10]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[na:na]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[test_a:6.0.10]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[test_a:6.0.10]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149) ~[na:na]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:166) ~[na:na]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[na:na]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[test_a:10.1.10]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[na:na]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[test_a:10.1.10]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[na:na]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:341) ~[na:na]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:391) ~[na:na]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[test_a:10.1.10]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:894) ~[na:na]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[na:na]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[test_a:10.1.10]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[na:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[na:na]
at [email protected]/java.lang.Thread.run(Thread.java:833) ~[test_a:na]
at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:807) ~[test_a:na]
at org.graalvm.nativeimage.builder/com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:210) ~[na:na]
附加信息
- 项目POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>test_a</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>test_a</name>
<description>test_a</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.37</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20230618</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 项目以Spring Native方式打包
# mvn clean native:compile -Pnative -DskipTests=true -T 10
# target/test_a
以上代码在jar包模式下运行无异常,只在GraalVM方式下有问题
纠正代码中错误 改为: String data = "[{"PD01A":{"PD01AD03":2,"PD01AD01":1}}]";
使用GraalVM 17.0.8 和GraalVM CE 17.0.8 问题是相同的
收到反馈,这个要晚点看,如果可以,也请你帮忙进来分析下原因。
咋修复的
我也没解决,换回jar包模式了
the same.request answer
@rootshk @imgoby @niaoshuai
FastJSON2版本:2.0.46
解决方案1:
1.
import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.hosted.RuntimeSerialization;
public class NativeConfig implements Feature {
@Override
public void beforeAnalysis(BeforeAnalysisAccess access) {
// PD01 PD01A需要实现 java.io.Serializable
RuntimeSerialization.register(X.PD01.class);
RuntimeSerialization.register(X.PD01A.class);
}
}
2. 然后Native Image
编译命令中添加 --features=xxx.xxx.NativeConfig
即可
解决方案2:SpringBoot 3.x
1.
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportRuntimeHints;
@Configuration
@ImportRuntimeHints(NativeConfig.class)
public class NativeConfig implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
// PD01 PD01A需要实现 java.io.Serializable
hints.serialization()
.registerType(X.PD01.class)
.registerType(X.PD01A.class)
;
}
}
@wssy001 按照你的方式,成功解決。非常感謝你的分享