Backend Development 7 min read

Is Creating a New ObjectMapper Every Call Killing Your Performance? A JMH Benchmark

This article examines the performance impact of instantiating a new Jackson ObjectMapper for each JSON parsing operation versus reusing a global instance, using JMH micro‑benchmarks to show that a shared ObjectMapper can be up to ten times faster.

macrozheng
macrozheng
macrozheng
Is Creating a New ObjectMapper Every Call Killing Your Performance? A JMH Benchmark
Since the frequent failures of fastjson, Jackson JSON library has become increasingly popular, especially as the default in the Spring family.

Many developers notice that Jackson lacks a fast

JSON.parseObject

-like method, so they instantiate a new ObjectMapper for each parsing.

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

This pattern is common among CV engineers, but its performance impact is questionable.

Is This Code Problematic?

Although the code works, creating a new ObjectMapper each call wastes memory and may affect execution time. ObjectMapper is thread‑safe and can be shared as a singleton.

To measure the impact, we use JMH (Java Microbenchmark Harness), a high‑precision benchmarking tool that can measure down to nanoseconds.

JMH Test Results

We benchmark three scenarios:

Instantiate ObjectMapper inside the method.

Use a globally shared ObjectMapper.

Use a ThreadLocal ObjectMapper per thread.

<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 output:

<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 results show that creating a new ObjectMapper per call yields about 2 million ops/s, while a shared global instance reaches over 20 million ops/s—a ten‑fold improvement. ThreadLocal provides a modest gain but not dramatic.

Conclusion

In most projects you should keep a single global ObjectMapper. It is thread‑safe, reduces memory allocation, and delivers far better performance. Only create separate instances when you need distinct configurations.

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.