fastjson2 icon indicating copy to clipboard operation
fastjson2 copied to clipboard

[BUG]2.0.11 fastjson1并发执行JSON.toJSONString异常

Open Trager324 opened this issue 1 year ago • 0 comments

问题描述

ForkJoinPool环境下对某些对象序列化时抛出异常 fastjson2暂未发现该问题

环境信息

  • OS信息: [e.g.:Windows]
  • JDK信息: [e.g.:Openjdk 1.8.0_321]
  • 版本信息:[e.g.:Fastjson 2.0.11]

重现步骤

junit-platform.properties配置如下

junit.jupiter.execution.parallel.enabled=true
junit.jupiter.execution.parallel.mode.default=concurrent
junit.jupiter.execution.parallel.mode.classes.default=concurrent
junit.jupiter.execution.parallel.config.strategy=fixed
junit.jupiter.execution.parallel.config.fixed.parallelism=2

并发执行ParallelTest中的测试用例,或者执行ContrastTest中的testParallel可能抛出异常

import com.alibaba.fastjson.JSON;
import lombok.Data;
import org.junit.jupiter.api.Test;

import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Stream;


public class ParallelTest {
    @Data
    static class Response<T> {
        T data;

        Response(T data) {
            this.data = data;
        }
    }

    @Data
    static class A {
        // 没有属性不会异常
        int a;
    }

    @Test
    void testB() {
        for (int i = 0; i < 100000; i++) {
            System.out.println(JSON.toJSONString(new Response<>(new A())));
        }
    }

    @Test
    void testList() {
        for (int i = 0; i < 100000; i++) {
            // Collections.singletonList(0)改成0也会异常,异常概率小一些
            System.out.println(JSON.toJSONString(new Response<>(Collections.singletonList(0))));
        }
    }
}

class ContrastTest {
    @Test
    void testParallel() {
        // 在ForkJoinPool中异常
        Stream.of(() -> {
                    for (int i = 0; i < 100000; i++) {
                        System.out.println(JSON.toJSONString(new ParallelTest.Response<>(Collections.singletonList(0))));
                    }
                },
                (Runnable)() -> {
                    for (int i = 0; i < 100000; i++) {
                        System.out.println(JSON.toJSONString(new ParallelTest.Response<>(new ParallelTest.A())));
                    }
                }).parallel().forEach(Runnable::run);
    }

    @Test
    void normal() throws InterruptedException {
        // 普通线程池中执行正常
        ExecutorService pool = Executors.newFixedThreadPool(2);
        CountDownLatch cdl = new CountDownLatch(2);
        pool.execute(() -> {
            for (int i = 0; i < 100000; i++) {
                System.out.println(JSON.toJSONString(new ParallelTest.Response<>(Collections.singletonList(0))));
            }
            cdl.countDown();
        });
        pool.execute(() -> {
            for (int i = 0; i < 100000; i++) {
                System.out.println(JSON.toJSONString(new ParallelTest.Response<>(new ParallelTest.A())));
            }
            cdl.countDown();
        });
        cdl.await();
        pool.shutdown();
    }
}

期待的正确结果

不抛出异常

相关日志输出

com.alibaba.fastjson.JSONException: toJSONString error

	at com.alibaba.fastjson.JSON.toJSONString(JSON.java:776)
	at ParallelTest.testList(ParallelTest.java:47)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)

附加信息

如果你还有其他需要提供的信息,可以在这里填写(可以提供截图、视频等)。

Trager324 avatar Aug 09 '22 11:08 Trager324