1

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.

Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136
Alex R
  • 11,364
  • 15
  • 100
  • 180
  • what version of jackson are you using – Yuri Sh Sep 26 '22 at 20:00
  • Jackson version is 2.13.1 – Alex R Sep 27 '22 at 00:36
  • Can you show how are you using Jackson? Bean configuration and an example of how you use it in a class for example. Also confirm that in you final jar/war the jackson version is really 2.13.1 (in case multiple version are being imported). – pringi Sep 27 '22 at 09:15
  • I am not configuring nor using Jackson directly in my code. It is managed by Springboot/Jetty to map json to/from object coming in and out of my @Controller methods. Which is why I'm suspicious of possible Springboot or Jetty bug. Checking the uber-jar produced by Springboot, I see jackson 2.13.1 jars in there, and no other version. – Alex R Sep 27 '22 at 16:03
  • Is there a large number of (possibly generated) classes in your system? Some proxy classes maybe? Not sure if the heap size shown also contains perm gen size, but maybe proxy objects get serialized/deserializedand and their classes don't get reused properly. – Pawel Zieminski Sep 30 '22 at 21:18
  • There are no generated classes, proxy classes, or anything else unusual. Just a bunch of POJOs. Problem still happening after upgrade to latest Springboot with Jackson 2.13.4. – Alex R Nov 30 '22 at 00:51
  • Where appropriate, please also include textual transcriptions of the text in your images. [See here](https://meta.stackoverflow.com/a/285557/11107541) for why. Also, a dump/log/error-message is good, but an actual [mre] is much better. – starball Dec 01 '22 at 21:51

1 Answers1

0

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.

Alex R
  • 11,364
  • 15
  • 100
  • 180