Fastjson2 性能优化指南

作为 Java 生态中最快速的 JSON 库之一,Fastjson2 在性能上进行了大量优化。但要想发挥其最大潜力,开发者需要掌握一些关键技巧。本文从下面7个方面介绍优化 Fastjson2 的性能。

1. 选择合适的 API 方法

Fastjson2 提供了多种序列化/反序列化方式,性能差异显著:

// ❌ 不推荐:使用 toJSONString 和 parseObject
String json = JSON.toJSONString(user);
User user = JSON.parseObject(json, User.class);

// ✅ 推荐:使用 toJSONBytes 和 parseObject(字节操作)
byte[] bytes = JSON.toJSONBytes(user);
User user = JSON.parseObject(bytes, User.class);

二进制JSON格式JSONB,它是Fastjson2独有的,适合高性能场景,字节操作在大规模并发或大数据量处理时非常明显,避免字符串编码转换,性能可提升 20-30%。

推荐字节操作(byte[])主要是为了减少字符编码转换的开销和内存抖动,但是对于日常的业务逻辑开发,保持现状即可,如果你在做性能优化,把 JSON 序列化这一层改为字节流操作,通常能获得 5%~15% 的整体性能提升。

2. 避免类型推导

对于泛型对象,避免每次调用时重新创建匿名类:

// ❌ 不推荐:每次调用都创建匿名类
List<User> users = JSON.parseObject(json, 
    new TypeReference<List<User>>(){}.getType());

// ✅ 推荐:预定义 TypeReference
static final TypeReference<List<User>> USER_LIST_TYPE = 
    new TypeReference<List<User>>(){};

List<User> users = JSON.parseObject(json, USER_LIST_TYPE);

虽然在代码里看起来只是少写了一行 new,但在 JVM 底层和 Fastjson 的处理逻辑中,“预定义”和“每次创建”有着本质的区别。
主要原因可以归纳为以下三点:

  • 反射只做一次,不再重复浪费 CPU每次 new 都要重新解析泛型类型;预定义只解析一次,后面直接复用。
  • 不频繁创建对象,GC 压力小、内存更稳每次 new 会产生临时对象 + 新类信息,导致元空间波动、频繁 GC;预定义只有一个静态对象,几乎不占 GC 开销。
  • Fastjson 缓存能稳定命中,速度更快固定的类型能让 Fastjson 直接命中缓存;每次 new 会让缓存命中率下降,速度变慢。

3. 使用对象复用模式

减少临时对象的创建能显著降低 GC 压力:

// 定义可复用的反序列化配置
static final FieldInfo fieldInfo = new FieldInfo();
static {
    fieldInfo.setFieldBased(true);
    fieldInfo.setIgnoreError(true);
}

// 批量反序列化时复用配置
public <T> List<T> parseArray(byte[] data, Class<T> clazz) {
    return JSON.parseArray(data, clazz, fieldInfo);
}

通过将反序列化配置对象定义为静态常量并复用,避免了每次调用时创建临时对象,从而显著减少内存分配和GC压力。

4. 禁用不必要的特性

根据场景关闭默认开启但无用的特性:

// ❌ 默认开启(但可能不需要)
JSONWriter.Feature.FieldBased  // 字段反射支持
JSONReader.Feature.AllowArbitraryCommas // 允许多余逗号

// ✅ 针对性优化
JSONWriter.Feature[] features = {
    // 关闭字段反射(如果使用 getter/setter)
    // 关闭 PrettyFormat(生产环境)
    JSONWriter.Feature.SkipTransientField
};

String json = JSON.toJSONString(obj, features);

5. 使用字节码增强(Lambda 工厂)

Fastjson2 支持 Lambda 工厂模式,大幅减少反射调用:

// 配置 Lambda 工厂(仅需一次)
static {
    JSONFactory.setDefaultFieldReaderCreator(
        (clazz, field) -> new FastjsonFieldReader(clazz, field) {
            @Override
            public Object readFieldValue(Object object) {
                // 使用 MethodHandle 直接访问
                return MethodHandles.lookup()
                    .unreflectGetter(field).invoke(object);
            }
        });
}

6. 批量处理时的内存优化

处理大量数据时,使用 InputStream/OutputStream:

// ❌ 不推荐:直接处理字符串
String json = readLargeFile();
List<User> users = JSON.parseArray(json, User.class);

// ✅ 推荐:流式处理
try (InputStream is = new FileInputStream("users.json")) {
    List<User> users = JSON.parseArray(is, 
        new byte[8192], // 自定义缓冲区大小
        User.class);
}

7. 性能数据对比

场景默认配置优化后提升幅度
小对象序列化 (1000次)45ms32ms28%
大数组反序列化 (10万条)1.2s0.8s33%
泛型反序列化8ms/次3ms/次60%

总结

性能优化的核心原则:减少对象创建、避免反射、使用原始字节操作、预编译类型信息。对于绝大多数业务场景,仅需遵循前三条建议就能获得显著提升。建议在正式环境运行性能基准测试,找到最适合自己场景的配置组合。

提示:不要过早优化!先用 JMH 等工具测试热点代码,再针对性地实施上述优化策略。