Skip to content
This repository has been archived by the owner on Oct 23, 2024. It is now read-only.

FASTJSON2 crushes JVM when polymorphism is used #4533

Open
undqurek opened this issue Sep 19, 2024 · 3 comments
Open

FASTJSON2 crushes JVM when polymorphism is used #4533

undqurek opened this issue Sep 19, 2024 · 3 comments

Comments

@undqurek
Copy link

undqurek commented Sep 19, 2024

Problem description

FASTJSON2 has problem to parse JSON to specific object by JSON.parseObject() mehod when polymorphism is used. Object type class inherits from some abstract class. To describe classes @JSONType annotation was used. The final result is crushed JVM.

Practical example

Used OS: Ubuntu 24.04.1 LTS x64

Used JVM:

openjdk version "21.0.4" 2024-07-16
OpenJDK Runtime Environment (build 21.0.4+7-Ubuntu-1ubuntu224.04)
OpenJDK 64-Bit Server VM (build 21.0.4+7-Ubuntu-1ubuntu224.04, mixed mode, sharing)

Note: the same problem occurs on Java 17 so it looks like the problem is common.

Used FASTJSON2:

<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.53</version>
    <scope>compile</scope>
</dependency>

Source code that crushes JVM (Program.java):

package com.example;

import java.util.List;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.annotation.JSONType;

public class Program {

    public static void main(String[] args) {

        MyFile myFile = new MyFile();
        myFile.type = "file";
        myFile.name = "my_file.txt";
        myFile.data = "Some content ...";

        MyDirectory myDirectory = new MyDirectory();
        myDirectory.type = "directory";
        myDirectory.name = "My directory";
        myDirectory.items = List.of(myFile);

        String json = JSON.toJSONString(myDirectory);
        MyDirectory object = JSON.parseObject(json, MyDirectory.class);  // <----- it crushes JVM
    }
}

@JSONType(
    typeKey = "type",
    seeAlso = {MyDirectory.class, MyFile.class}
)
abstract class MyNode {
    public String type;
    public String name;
}

@JSONType(typeName = "file")
class MyFile extends MyNode {
    public String data;
}

@JSONType(typeName = "directory")
class MyDirectory extends MyNode {
    public List<MyNode> items;
}

Console output:

/usr/bin/env /usr/lib/jvm/java-21-openjdk-amd64/bin/java @/tmp/cp_9jg5za4k5xz0ewd7mvown6x99.argfile com.example.Program 
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007b72ea7b7fb1, pid=64235, tid=64236
#
# JRE version: OpenJDK Runtime Environment (21.0.4+7) (build 21.0.4+7-Ubuntu-1ubuntu224.04)
# Java VM: OpenJDK 64-Bit Server VM (21.0.4+7-Ubuntu-1ubuntu224.04, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x9b7fb1]  AccessInternal::PostRuntimeDispatch<G1BarrierSet::AccessBarrier<401510ul, G1BarrierSet>, (AccessInternal::BarrierType)1, 401510ul>::oop_access_barrier(oopDesc*, long, oopDesc*)+0x51
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /home/john/Desktop/tmp/java/alibaba_fastjson2_polymorphism/core.64235)
#
# An error report file with more information is saved as:
# /home/john/Desktop/tmp/java/alibaba_fastjson2_polymorphism/hs_err_pid64235.log
#
# If you would like to submit a bug report, please visit:
#   https://bugs.launchpad.net/ubuntu/+source/openjdk-21
#
Aborted (core dumped)

JVM logs (hs_err_pid64235.log):

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007b72ea7b7fb1, pid=64235, tid=64236
#
# JRE version: OpenJDK Runtime Environment (21.0.4+7) (build 21.0.4+7-Ubuntu-1ubuntu224.04)
# Java VM: OpenJDK 64-Bit Server VM (21.0.4+7-Ubuntu-1ubuntu224.04, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x9b7fb1]  AccessInternal::PostRuntimeDispatch<G1BarrierSet::AccessBarrier<401510ul, G1BarrierSet>, (AccessInternal::BarrierType)1, 401510ul>::oop_access_barrier(oopDesc*, long, oopDesc*)+0x51
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /home/john/Desktop/tmp/java/alibaba_fastjson2_polymorphism/core.64235)
#
# If you would like to submit a bug report, please visit:
#   https://bugs.launchpad.net/ubuntu/+source/openjdk-21
#

---------------  S U M M A R Y ------------

Command Line: -XX:+ShowCodeDetailsInExceptionMessages com.example.Program

Host: AMD Ryzen 9 5900X 12-Core Processor, 32 cores, 62G, Ubuntu 24.04.1 LTS
Time: Thu Sep 19 14:23:18 2024 CEST elapsed time: 0.171075 seconds (0d 0h 0m 0s)

---------------  T H R E A D  ---------------

Current thread (0x00007b72e4019a30):  JavaThread "main"             [_thread_in_vm, id=64236, stack(0x00007b72e9900000,0x00007b72e9a00000) (1024K)]

Stack: [0x00007b72e9900000,0x00007b72e9a00000],  sp=0x00007b72e99fe4b0,  free space=1017k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x9b7fb1]  AccessInternal::PostRuntimeDispatch<G1BarrierSet::AccessBarrier<401510ul, G1BarrierSet>, (AccessInternal::BarrierType)1, 401510ul>::oop_access_barrier(oopDesc*, long, oopDesc*)+0x51
V  [libjvm.so+0xfa9237]  Unsafe_PutReference+0xb7
j  jdk.internal.misc.Unsafe.putReference(Ljava/lang/Object;JLjava/lang/Object;)V+0 [email protected]
j  sun.misc.Unsafe.putObject(Ljava/lang/Object;JLjava/lang/Object;)V+7 [email protected]
j  com.alibaba.fastjson2.reader.FieldReaderStringField.readFieldValue(Lcom/alibaba/fastjson2/JSONReader;Ljava/lang/Object;)V+73
j  com.alibaba.fastjson2.reader.ObjectReaderSeeAlso.readObject(Lcom/alibaba/fastjson2/JSONReader;Ljava/lang/reflect/Type;Ljava/lang/Object;J)Ljava/lang/Object;+860
j  com.alibaba.fastjson2.reader.ORG_1_3_MyDirectory.readObject(Lcom/alibaba/fastjson2/JSONReader;Ljava/lang/reflect/Type;Ljava/lang/Object;J)Ljava/lang/Object;+631
j  com.alibaba.fastjson2.JSON.parseObject(Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;+67
j  com.example.Program.main([Ljava/lang/String;)V+62
v  ~StubRoutines::call_stub 0x00007b72d3c5fcc6
V  [libjvm.so+0x90841a]  JavaCalls::call_helper(JavaValue*, methodHandle const&, JavaCallArguments*, JavaThread*)+0x2da
V  [libjvm.so+0x9ae72d]  jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, JavaThread*) [clone .constprop.1]+0x35d
V  [libjvm.so+0x9b0c7f]  jni_CallStaticVoidMethod+0x12f
C  [libjli.so+0x55be]  JavaMain+0xfde
C  [libjli.so+0x844d]  ThreadJavaMain+0xd
C  [libc.so.6+0x9ca94]
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  jdk.internal.misc.Unsafe.putReference(Ljava/lang/Object;JLjava/lang/Object;)V+0 [email protected]
j  sun.misc.Unsafe.putObject(Ljava/lang/Object;JLjava/lang/Object;)V+7 [email protected]
j  com.alibaba.fastjson2.reader.FieldReaderStringField.readFieldValue(Lcom/alibaba/fastjson2/JSONReader;Ljava/lang/Object;)V+73
j  com.alibaba.fastjson2.reader.ObjectReaderSeeAlso.readObject(Lcom/alibaba/fastjson2/JSONReader;Ljava/lang/reflect/Type;Ljava/lang/Object;J)Ljava/lang/Object;+860
j  com.alibaba.fastjson2.reader.ORG_1_3_MyDirectory.readObject(Lcom/alibaba/fastjson2/JSONReader;Ljava/lang/reflect/Type;Ljava/lang/Object;J)Ljava/lang/Object;+631
j  com.alibaba.fastjson2.JSON.parseObject(Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;+67
j  com.example.Program.main([Ljava/lang/String;)V+62
v  ~StubRoutines::call_stub 0x00007b72d3c5fcc6

siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000000000000010

...
...
...

vm_info: OpenJDK 64-Bit Server VM (21.0.4+7-Ubuntu-1ubuntu224.04) for linux-amd64 JRE (21.0.4+7-Ubuntu-1ubuntu224.04), built on 2024-07-23T01:34:52Z by "buildd" with gcc 13.2.0

END.
@GGGGGHT
Copy link

GGGGGHT commented Sep 21, 2024

Just remove the abstract modifier from the MyNode class.

@undqurek
Copy link
Author

Thanks. It works, but I think it could be good to add some exception to know what is going on.

@GGGGGHT
Copy link

GGGGGHT commented Sep 25, 2024

Adding exception information seems to be feasible, Maybe you need to report it in another repository instead of here.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants