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