Backend Development 8 min read

Why Reusing a Single Jackson ObjectMapper Boosts JSON Performance 10×

This article explains how repeatedly creating Jackson ObjectMapper instances hurts performance, demonstrates a JMH benchmark comparing new, singleton, and ThreadLocal ObjectMapper usages, and concludes that a single globally shared ObjectMapper can achieve up to ten times faster JSON parsing.

macrozheng
macrozheng
macrozheng
Why Reusing a Single Jackson ObjectMapper Boosts JSON Performance 10×

Background

Since the frequent security issues of fastjson, Jackson has become the default JSON library in the Spring ecosystem, but many developers notice that it lacks a simple

JSON.parseObject

-style method and requires creating an

ObjectMapper

instance for each conversion.

<code>public String getCarString(Car car) {
    ObjectMapper objectMapper = new ObjectMapper();
    String str = objectMapper.writeValueAsString(car);
    return str;
}
</code>

This pattern appears widely in CV engineering code and raises the question of whether repeatedly instantiating

ObjectMapper

hurts performance.

Is the Code Problematic?

Although the code works, creating a new

ObjectMapper

on every call wastes memory and may impact speed.

ObjectMapper

is thread‑safe and can be shared as a singleton.

Benchmark with JMH

To answer the performance question we use JMH (Java Microbenchmark Harness), a high‑precision benchmarking tool that can measure operations at the nanosecond level.

<code>@BenchmarkMode({Mode.Throughput})
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@Threads(10)
public class ObjectMapperTest {
    String json = "{\"color\":\"Black\",\"type\":\"BMW\"}";

    @State(Scope.Benchmark)
    public static class BenchmarkState {
        ObjectMapper GLOBAL_MAP = new ObjectMapper();
        ThreadLocal<ObjectMapper> GLOBAL_MAP_THREAD = new ThreadLocal<>();
    }

    @Benchmark
    public Map globalTest(BenchmarkState state) throws Exception {
        Map map = state.GLOBAL_MAP.readValue(json, Map.class);
        return map;
    }

    @Benchmark
    public Map globalTestThreadLocal(BenchmarkState state) throws Exception {
        if (null == state.GLOBAL_MAP_THREAD.get()) {
            state.GLOBAL_MAP_THREAD.set(new ObjectMapper());
        }
        Map map = state.GLOBAL_MAP_THREAD.get().readValue(json, Map.class);
        return map;
    }

    @Benchmark
    public Map localTest() throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();
        Map map = objectMapper.readValue(json, Map.class);
        return map;
    }

    public static void main(String[] args) throws Exception {
        Options opts = new OptionsBuilder()
                .include(ObjectMapperTest.class.getSimpleName())
                .resultFormat(ResultFormatType.CSV)
                .build();
        new Runner(opts).run();
    }
}
</code>

Benchmark results:

<code>Benchmark                                 Mode  Cnt          Score          Error  Units
ObjectMapperTest.globalTest                thrpt    5  25125094.559 ± 1754308.010  ops/s
ObjectMapperTest.globalTestThreadLocal    thrpt    5  31780573.549 ± 7779240.155  ops/s
ObjectMapperTest.localTest                thrpt    5   2131394.345 ±  216974.682  ops/s
</code>

The single global

ObjectMapper

processes about 20 million JSON parses per second, roughly ten times faster than creating a new instance each time. Using a

ThreadLocal

gives a modest improvement but not a dramatic one.

Conclusion

For typical projects you should keep one globally shared

ObjectMapper

. It is thread‑safe, reduces memory churn, and delivers an order‑of‑magnitude performance gain. Separate instances are only justified when you need distinct configuration for different use cases.

JavaPerformanceBenchmarkJacksonJMHObjectMapper
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login 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.