Search code examples
spring-bootmemory-leaksjacksoneclipse-memory-analyzer

Memory Leak in Jackson ObjectMapper's SerializerCache


Not quite sure if this is a Jackson question or a Springboot question, or Jetty:

My microservice became unresponsive in production apparently due to excessive memory usage (telling from OS RSS stat) but no OOM.

I obtained a heap dump via jcmd [pid] GC.heap_dump and later opened it in Eclipse Memory Analyzer Tool (MAT) installed via Eclipse Marketplace.

I'm greeted by this finding:

enter image description here

I think this says Jackson ObjectMapper ate 80% of my heap (395M out of the default 512M size).

What would cause this and how can I prevent it?

UPDATES

I started digging into Jackson's SeralizerCache.

There was indeed a reproducible memory leak but it was fixed in 2.7.x: https://github.com/FasterXML/jackson-databind/issues/1049

This SO question also applied to pre-2.7 versions: Too Many objects in single instance of ObjectMapper SerializerCache causing memory leak

My version is 2.13.1, so the above shouldn't matter.


Solution

  • Found the culprit:

    @PostMapping(value = "/headers", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public ListingHeader[] head(@RequestBody ListingDetailPK[] parms) {
        final ListingInfo[] all = readerDao.getAll(Arrays.asList(parms));
        ObjectMapper mapper = JSON.mapper().copy();
        mapper.registerModule(new MrBeanModule());
        try {
            return mapper.readValue(mapper.writerFor(ListingHeader[].class)
                    .writeValueAsString(all), ListingHeader[].class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
    

    A clue was provided in a comment by @Pawel Zieminski:

    Is there a large number of (possibly generated) classes in your system? Some proxy classes maybe?

    I suspect that the dynamic proxies generated by MrBeanModule are causing the problem.