Why Replacing Fastjson with Gson Can Crash Your Service – A Deep Serialization Study

An in‑depth analysis reveals how replacing Fastjson with Gson caused a 400 MB payload and OOM in production, comparing serialization size, reference handling, and throughput across Gson, Fastjson, Java native serialization, and Hessian2, and offering recommendations for choosing the right framework.

Programmer DD
Programmer DD
Programmer DD
Why Replacing Fastjson with Gson Can Crash Your Service – A Deep Serialization Study

Preface

JSON serialization frameworks have long been a security concern; fastjson has attracted many vulnerabilities recently, prompting security teams to demand upgrades. To avoid these issues, we replaced fastjson with Gson in a project, which led to an unexpected OOM problem in production.

Problem Description

A simple service serialized an object with fastjson and sent it via HTTP. After switching to Gson, the service generated a 400 MB request, which the HTTP client sent without size checks, causing the service to become unavailable.

Problem Analysis

Gson serializes each repeated object separately, while fastjson uses reference markers ($ref) for duplicate objects. In our data, many fields were duplicated, exposing Gson's inability to handle repeated objects efficiently.

Example code demonstrates the issue:

Foo foo = new Foo();
Bar bar = new Bar();
List<Foo> foos = new ArrayList<>();
for (int i = 0; i < 3; i++) {
    foos.add(foo);
}
bar.setFoos(foos);
Gson gson = new Gson();
String gsonStr = gson.toJson(bar);
System.out.println(gsonStr);
String fastjsonStr = JSON.toJSONString(bar);
System.out.println(fastjsonStr);

The output shows Gson repeats the object, while fastjson uses $ref.

Compression Ratio Test

Serialized object contains many attributes to simulate real business data.

Duplicate count: 200 identical references in a List.

Serialization methods: Gson, Fastjson, Java native, Hessian2.

Primary metric: compressed byte size; secondary: whether deserialized list preserves object identity.

public class Main {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Foo foo = new Foo();
        Bar bar = new Bar();
        List<Foo> foos = new ArrayList<>();
        for (int i = 0; i < 200; i++) {
            foos.add(foo);
        }
        bar.setFoos(foos);
        // gson
        Gson gson = new Gson();
        String gsonStr = gson.toJson(bar);
        System.out.println(gsonStr.length());
        Bar gsonBar = gson.fromJson(gsonStr, Bar.class);
        System.out.println(gsonBar.getFoos().get(0) == gsonBar.getFoos().get(1));
        // fastjson
        String fastjsonStr = JSON.toJSONString(bar);
        System.out.println(fastjsonStr.length());
        Bar fastjsonBar = JSON.parseObject(fastjsonStr, Bar.class);
        System.out.println(fastjsonBar.getFoos().get(0) == fastjsonBar.getFoos().get(1));
        // java
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(bar);
        oos.close();
        System.out.println(baos.toByteArray().length);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
        Bar javaBar = (Bar) ois.readObject();
        ois.close();
        System.out.println(javaBar.getFoos().get(0) == javaBar.getFoos().get(1));
        // hessian2
        ByteArrayOutputStream hessianBaos = new ByteArrayOutputStream();
        Hessian2Output hOut = new Hessian2Output(hessianBaos);
        hOut.writeObject(bar);
        hOut.close();
        System.out.println(hessianBaos.toByteArray().length);
        ByteArrayInputStream hessianBais = new ByteArrayInputStream(hessianBaos.toByteArray());
        Hessian2Input hIn = new Hessian2Input(hessianBais);
        Bar hessianBar = (Bar) hIn.readObject();
        hIn.close();
        System.out.println(hessianBar.getFoos().get(0) == hessianBar.getFoos().get(1));
    }
}

Results:

gson:
62810
false

fastjson:
4503
true

Java:
1540
true

Hessian2:
686
true

Conclusion: Fastjson’s reference handling dramatically reduces payload size; Hessian2 achieves the best compression, while Java native serialization also outperforms Gson.

Throughput Test

Benchmarking the four serializers shows fastjson achieving the highest throughput, followed by Gson, Hessian2, and Java.

Benchmark                Mode  Cnt    Score          Error  Units
MicroBenchmark.fastjson  thrpt   25  6724809.416 ± 1542197.448 ops/s
MicroBenchmark.gson      thrpt   25  1508825.440 ±  194148.657 ops/s
MicroBenchmark.hessian2  thrpt   25   758643.567 ±  239754.709 ops/s
MicroBenchmark.java      thrpt   25   734624.615 ±   66892.728 ops/s

Fastjson’s text‑based serialization delivers throughput an order of magnitude higher than binary alternatives.

Overall Test Conclusions

Fastjson’s $ref markers can be deserialized by Gson, but Gson cannot emit them.

Fastjson, Hessian2, and Java support circular references; Gson does not.

Fastjson can disable circular‑reference detection.

Gson loses object identity after a round‑trip, potentially inflating memory usage.

Hessian2 provides the best compression for large payloads.

Fastjson offers the highest throughput, suitable for high‑speed scenarios.

When choosing a serializer, consider reference handling, compression, throughput, and compatibility; Hessian2 and Fastjson are recommended for most cases.

Summary

Fastjson sacrifices safety for speed, leading to many vulnerabilities, but trade‑offs are inevitable. The best serializer depends on the specific problem; while Jackson may be superior in some aspects, the chosen library must meet the project's requirements.

Replacing a serialization framework should be done cautiously, ensuring the new library covers the features previously relied upon.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

hessian2
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.