public class App {
public static void main(String[] args) throws Exception {
String json = """
{"height":800,"size":"LARGE","title":"image","transparent":"false","uri":"file://image.png","width":600}
""";
System.out.println("original json: " + json);
Image image = JSON.parseObject(json, Image.class);
System.out.println("image from original json: " + image);
String jsonString = JSON.toJSONString(image);
System.out.println("toJSONString: " + jsonString);
image = JSON.parseObject(jsonString, Image.class);
System.out.println("image image from toJSONString: " + image);
}
}
@com.alibaba.fastjson2.annotation.JSONCompiled
public class Image
implements java.io.Serializable {
private int height;
private Size size;
private String title;
private String uri;
private int width;
private boolean transparent;
public Image() {
}
public void setUri(String uri) {
this.uri = uri;
}
public void setTitle(String title) {
this.title = title;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public void setSize(Size size) {
this.size = size;
}
public String getUri() {
return uri;
}
public String getTitle() {
return title;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Size getSize() {
return size;
}
public enum Size {
SMALL, LARGE
}
public boolean isTransparent() {
return transparent;
}
public void setTransparent(boolean transparent) {
this.transparent = transparent;
}
}
期待的正确结果
Deserialized from json string successfully.
相关日志输出
original json: {"height":800,"size":"LARGE","title":"image","transparent":"false","uri":"file://image.png","width":600}
image from original json: io.suragreat.issue.fastjson2.graalvm_native.vo.Image@3c49d008
toJSONString: {"height":800,"size":"LARGE","title":"image","transparent":false,"uri":"file://image.png","width":600}
Exception in thread "main" com.alibaba.fastjson2.JSONException: syntax error : 102
at com.alibaba.fastjson2.JSONReaderUTF8.readBoolValue(JSONReaderUTF8.java:7550)
at com.alibaba.fastjson2.reader.FieldReaderBoolValueMethod.readFieldValue(FieldReaderBoolValueMethod.java:26)
at com.alibaba.fastjson2.reader.ObjectReader6.readObject(ObjectReader6.java:389)
at com.alibaba.fastjson2.JSON.parseObject(JSON.java:864)
at io.suragreat.issue.fastjson2.graalvm_native.App.main(App.java:18)
Root Cause
The root cause is incorrectly Using Unsafe safely in GraalVM Native Image. From the native image building info, there're some warning listed as below:
Warning: RecomputeFieldValue.ArrayBaseOffset automatic substitution failed. The automatic substitution registration was attempted because a call to jdk.internal.misc.Unsafe.arrayBaseOffset(Class) was detected in the static initializer of com.alibaba.fastjson2.util.JDKUtils. Detailed failure reason(s): Could not determine the field where the value produced by the call to jdk.internal.misc.Unsafe.arrayBaseOffset(Class) for the array base offset computation is stored. The call is not directly followed by a field store or by a sign extend node followed directly by a field store.
Warning: RecomputeFieldValue.FieldOffset automatic substitution failed. The automatic substitution registration was attempted because a call to sun.misc.Unsafe.objectFieldOffset(Field) was detected in the static initializer of com.alibaba.fastjson2.util.JDKUtils. Detailed failure reason(s): Could not determine the field where the value produced by the call to sun.misc.Unsafe.objectFieldOffset(Field) for the field offset computation is stored. The call is not directly followed by a field store or by a sign extend node followed directly by a field store.
Warning: RecomputeFieldValue.FieldOffset automatic substitution failed. The automatic substitution registration was attempted because a call to sun.misc.Unsafe.objectFieldOffset(Field) was detected in the static initializer of com.alibaba.fastjson2.util.JDKUtils. Detailed failure reason(s): Could not determine the field where the value produced by the call to sun.misc.Unsafe.objectFieldOffset(Field) for the field offset computation is stored. The call is not directly followed by a field store or by a sign extend node followed directly by a field store.
Warning: RecomputeFieldValue.FieldOffset automatic substitution failed. The automatic substitution registration was attempted because a call to sun.misc.Unsafe.objectFieldOffset(Field) was detected in the static initializer of com.alibaba.fastjson2.util.JDKUtils. Detailed failure reason(s): Could not determine the field where the value produced by the call to sun.misc.Unsafe.objectFieldOffset(Field) for the field offset computation is stored. The call is not directly followed by a field store or by a sign extend node followed directly by a field store.
Warning: RecomputeFieldValue.FieldOffset automatic substitution failed. The automatic substitution registration was attempted because a call to sun.misc.Unsafe.objectFieldOffset(Field) was detected in the static initializer of com.alibaba.fastjson2.util.JDKUtils. Detailed failure reason(s): The argument of sun.misc.Unsafe.objectFieldOffset(java.lang.reflect.Field) is not a constant value or a field load that can be constant-folded., Could not determine the field where the value produced by the call to sun.misc.Unsafe.objectFieldOffset(Field) for the field offset computation is stored. The call is not directly followed by a field store or by a sign extend node followed directly by a field store.
Warning: RecomputeFieldValue.FieldOffset automatic substitution failed. The automatic substitution registration was attempted because a call to sun.misc.Unsafe.objectFieldOffset(Field) was detected in the static initializer of com.alibaba.fastjson2.util.JDKUtils. Detailed failure reason(s): Could not determine the field where the value produced by the call to sun.misc.Unsafe.objectFieldOffset(Field) for the field offset computation is stored. The call is not directly followed by a field store or by a sign extend node followed directly by a field store.
问题描述
If a bean contains a boolean field, it can't be deserialized with false value in GraalVM native image.
环境信息
重现步骤
I'd created a demo repo in: https://github.com/suragreat/fastjson2-native.
To run:
mvn clean package -Pnative
./target/my-app
期待的正确结果
Deserialized from json string successfully.
相关日志输出
original json: {"height":800,"size":"LARGE","title":"image","transparent":"false","uri":"file://image.png","width":600}
image from original json: io.suragreat.issue.fastjson2.graalvm_native.vo.Image@3c49d008 toJSONString: {"height":800,"size":"LARGE","title":"image","transparent":false,"uri":"file://image.png","width":600} Exception in thread "main" com.alibaba.fastjson2.JSONException: syntax error : 102 at com.alibaba.fastjson2.JSONReaderUTF8.readBoolValue(JSONReaderUTF8.java:7550) at com.alibaba.fastjson2.reader.FieldReaderBoolValueMethod.readFieldValue(FieldReaderBoolValueMethod.java:26) at com.alibaba.fastjson2.reader.ObjectReader6.readObject(ObjectReader6.java:389) at com.alibaba.fastjson2.JSON.parseObject(JSON.java:864) at io.suragreat.issue.fastjson2.graalvm_native.App.main(App.java:18)
Root Cause
The root cause is incorrectly Using Unsafe safely in GraalVM Native Image. From the native image building info, there're some warning listed as below:
According to https://developers.redhat.com/articles/2022/05/09/using-unsafe-safely-graalvm-native-image#unsafe_proves_to_be_unsafe, the
static
field incom.alibaba.fastjson2.util.JDKUtils
which is assigned from UnSafe offset must be marked asfinal
. It works after modification as below: