Skip to content

[BUG] fastjson2版本2.0.59后使用java.util.Collections#EMPTY_LIST序列化报错 #3828

@huaweiqq99

Description

@huaweiqq99

问题描述

FastJSON2版本从2.0.49升级到2.0.59后,在Dubbo框架中反序列化包含Collections.EMPTY_LIST的对象时抛出异常。错误信息显示IllegalAccessException: Class com.alibaba.fastjson2.reader.ObjectReaderImplListStr can not access a member of class java.util.Collections$EmptyList with modifiers "private"

环境信息

请填写以下信息:

  • OS信息:Linux/Windows
  • JDK信息:JDK 21
  • 版本信息:Fastjson2 2.0.59(从2.0.49升级后出现问题)
  • 框架信息:Apache Dubbo

重现步骤

如何操作可以重现该问题:

  1. 创建一个包含Collections.EMPTY_LIST字段的Java对象
  2. 在Dubbo服务中返回该对象
  3. 客户端调用服务时,FastJSON2尝试反序列化该对象
  4. 出现IllegalAccessException错误,无法访问Collections$EmptyList的私有成员
import java.util.Collections;
import java.util.List;

// 示例返回对象
public class ResponseObject {
    private String name;
    private List<String> items = Collections.EMPTY_LIST; // 问题所在
    
    // getter/setter方法
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public List<String> getItems() { return items; }
    public void setItems(List<String> items) { this.items = items; }
}

// Dubbo服务接口
public interface TestService {
    ResponseObject getResponse();
}

// Dubbo服务实现
@Service
public class TestServiceImpl implements TestService {
    @Override
    public ResponseObject getResponse() {
        ResponseObject response = new ResponseObject();
        response.setName("test");
        // items字段默认为Collections.EMPTY_LIST
        return response; // 这里会在客户端反序列化时出错
    }
}

期待的正确结果

对您期望发生的结果进行清晰简洁的描述。

期望FastJSON2能够正确处理Collections.EMPTY_LIST的序列化和反序列化,就像在2.0.49版本中一样正常工作,不应该因为访问权限问题而抛出IllegalAccessException

相关日志输出

请复制并粘贴任何相关的日志输出。

java.io.IOException: org.apache.dubbo.common.serialize.SerializationException: com.alibaba.fastjson2.JSONException: create instance error class java.util.Collections$EmptyList, offset 213
	at org.apache.dubbo.common.serialize.DefaultSerializationExceptionWrapper.handleToIOException(DefaultSerializationExceptionWrapper.java:358)
	at org.apache.dubbo.common.serialize.DefaultSerializationExceptionWrapper.access$000(DefaultSerializationExceptionWrapper.java:28)
	at org.apache.dubbo.common.serialize.DefaultSerializationExceptionWrapper$ProxyObjectInput.readObject(DefaultSerializationExceptionWrapper.java:177)
	at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcResult.handleValue(DecodeableRpcResult.java:192)
	at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcResult.decode(DecodeableRpcResult.java:125)
	... (省略部分堆栈信息)
Caused by: org.apache.dubbo.common.serialize.SerializationException: com.alibaba.fastjson2.JSONException: create instance error class java.util.Collections$EmptyList, offset 213
	... 222 more
Caused by: com.alibaba.fastjson2.JSONException: create instance error class java.util.Collections$EmptyList, offset 213
	at com.alibaba.fastjson2.reader.ObjectReaderImplListStr.readJSONBObject(ObjectReaderImplListStr.java:153)
	at com.alibaba.fastjson2.reader.FieldReaderObject.readFieldValueJSONB(FieldReaderObject.java:206)
	at com.alibaba.fastjson2.reader.ObjectReaderAdapter.readFieldValue(ObjectReaderAdapter.java:507)
	at com.alibaba.fastjson2.JSONB.parseObject(JSONB.java:879)
	at org.apache.dubbo.common.serialize.fastjson2.FastJson2ObjectInput.readObject(FastJson2ObjectInput.java:151)
	... 219 more
Caused by: java.lang.IllegalAccessException: Class com.alibaba.fastjson2.reader.ObjectReaderImplListStr can not access a member of class java.util.Collections$EmptyList with modifiers "private"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
	at java.lang.Class.newInstance(Class.java:436)
	at com.alibaba.fastjson2.reader.ObjectReaderImplListStr.readJSONBObject(ObjectReaderImplListStr.java:151)
	... 225 more

问题分析:

  1. Collections.EMPTY_LISTCollections$EmptyList的实例,该类的构造函数是私有的
  2. FastJSON2 2.0.59版本在反序列化时尝试通过反射调用Collections$EmptyList的构造函数
  3. 由于访问权限限制,抛出IllegalAccessException异常
  4. 该问题在FastJSON2 2.0.49版本中不存在,说明是版本升级引入的回归问题

影响范围:

  • 所有使用Collections.EMPTY_LISTCollections.EMPTY_SETCollections.EMPTY_MAP作为默认值的对象
  • 在Dubbo等RPC框架中传输此类对象时会失败
  • 影响生产环境的稳定性

临时解决方案:

  1. Collections.EMPTY_LIST替换为new ArrayList<>()
  2. 或者使用Collections.emptyList()方法
  3. 降级到FastJSON2 2.0.46版本
// 问题代码
private List<String> items = Collections.EMPTY_LIST;

// 临时解决方案1
private List<String> items = new ArrayList<>();

// 临时解决方案2  
private List<String> items = Collections.emptyList();

建议的修复方案:
FastJSON2应该为Collections$EmptyList等JDK内置的不可变集合类提供特殊处理,而不是尝试通过反射创建实例。

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfixed

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions