2

Closed

Memory leak in JsonMediaTypeFormatter when SerializerSettings.ReferenceResolver is used

description

JsonMediaTypeFormatter has a public property to access the SerializerSettings, you can set ReferenceResolver to your custom class.

When the media type formatter creates the JsonSerializer instances, it simply passes the serializer settings to the json serializer. Json.NET will use the assigned ReferenceResolver and add items to it. This has two side effectes:
  1. The resolver has to be thrad-safe and might mix references from different thread which use the media type formatter at the same time.
  2. When serialization finishes, the resolver is not notified, so it cannot clear its internal lists. References stay in the dictionary forever and the GC will never free the memory.
This all only happens when you assign your own ReferenceResolver instance. When you leave it as default (null), a new resolver is instantiated for each serialization/deserialization. But in current implementation, ReferenceResolver is nearby useless.
Closed Jan 23, 2013 at 5:06 AM by JamesNK
I'm going to close this because there isn't anything I can do. I suggest you raise the issue on the Web API CodePlex website.

comments

JamesNK wrote Jan 22, 2013 at 7:15 AM

ReferenceResolvers can be implemented however you want but I imagine it being static, use caching internally and being shared.

If no resolver is assigned Json.NET uses a shared instance of DefaultContractResolver and that works quite well.

I'll leave this open to remind me to add some advice to the documentation about how a resolver is best used.

JamesNK wrote Jan 22, 2013 at 7:15 AM

ReferenceResolvers can be implemented however you want but I imagine it being static, use caching internally and being shared.

If no resolver is assigned Json.NET uses a shared instance of DefaultContractResolver and that works quite well.

I'll leave this open to remind me to add some advice to the documentation about how a resolver is best used.

CarstenSchuette wrote Jan 22, 2013 at 8:00 AM

I think Json.NET does not use a shared DefaultContractResolver for resolving references, but a DefaultReferenceResolver. And it does not use a shared static instance, but creates a new one for each JsonSerializer instance. That's why there is no problem with references that are hold in the resolvers internal Dictionary when using JsonSerializer directly.

But when using a JsonMediaTypeFormatter, the custom binding resolver is bound to the media type formatter instance, and this is a problem because you only have one media type formatter instance in your global http configuration. How should the custom binding resolver know when to flush outdated references?

JamesNK wrote Jan 22, 2013 at 8:19 AM

Ohh, a reference resolver. Sorry, I thought you were talking about a contract resolver.

I think the issue is more how Web API is using a single instance of JsonSerializerSettings. What it needs is an event that you can hook into when a serializer is created and assign an reference resolver then.