Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

After Jackson serializes a large number of objects, the metadata space of the JVM cannot be freed #1321

Closed
dylan-tao opened this issue Jul 25, 2024 · 11 comments

Comments

@dylan-tao
Copy link

dylan-tao commented Jul 25, 2024

Version: 2.13.5

Description: After Jackson serializes a large number of objects, when the Classloader unloads the loaded class, Jackson refers to the serialized object and cannot free the JVM's metadata space

Expectation: When the classloader unloads a loaded class, it can explicitly manually release or unload the serialized class, allowing the JVM to automatically reclaim and release it when the meta space is full

@cowtowncoder
Copy link
Member

ObjectMapper will cache serializers and deserializers, which will have to depend on classes being handled (via Reflection-accessed Methods, Fields etc).
There is no way around that; (de)serializer caching/reuse is an absolute must for performance reasons.

But as long as you drop reference to ObjectMapper (and possible ObjectReaders, ObjectWriters), those references would go away.
Perhaps you can use Soft- (or was it Weak-) Reference for mapper if this is important thing to do.

@pjfanning
Copy link
Member

@cowtowncoder @dylan-tao TypeFactory has a singleton instance that may hold onto Class references.

Its cache can be cleared explicitly using:

com.fasterxml.jackson.databind.type.TypeFactory.defaultInstance().clearCache();

@cowtowncoder
Copy link
Member

Good point, @pjfanning. It's an unfortunate thing, global stateful (wrt caching) singleton :-(

@dylan-tao
Copy link
Author

@cowtowncoder @dylan-tao TypeFactory has a singleton instance that may hold onto Class references.

Its cache can be cleared explicitly using:

com.fasterxml.jackson.databind.type.TypeFactory.defaultInstance().clearCache();

Thanks, I'll test it and wait for my good news.

@dylan-tao
Copy link
Author

Good point, @pjfanning. It's an unfortunate thing, global stateful (wrt caching) singleton :-(

@cowtowncoder @dylan-tao TypeFactory has a singleton instance that may hold onto Class references.

Its cache can be cleared explicitly using:

com.fasterxml.jackson.databind.type.TypeFactory.defaultInstance().clearCache();

Unfortunately, it still cannot be released. I found that the jackson cache in the following figure has not been released. Can you provide the cache release method in the information?
企业微信截图_17219901112254
企业微信截图_17219906612318

@dylan-tao
Copy link
Author

dylan-tao commented Jul 26, 2024

Good point, @pjfanning. It's an unfortunate thing, global stateful (wrt caching) singleton :-(

@cowtowncoder @dylan-tao TypeFactory has a singleton instance that may hold onto Class references.
Its cache can be cleared explicitly using:

com.fasterxml.jackson.databind.type.TypeFactory.defaultInstance().clearCache();

Unfortunately, it still cannot be released. I found that the jackson cache in the following figure has not been released. Can you provide the cache release method in the information? 企业微信截图_17219901112254 企业微信截图_17219906612318

If you want to view it in real time, I provide the log of the stack, and import and analyze the following files through Eclipse Memory Analyzer to see the relevant jackson reference information in the figure above.

Heap File:https://drive.google.com/file/d/1ncTJuMLZRncyGXSqhlbU-h6wM8Sy1-sB/view?usp=sharing
Eclipse Memory Analyzer:https://eclipse.dev/mat/downloads.php

@pjfanning
Copy link
Member

Would you not consider using microservices? If having the overhead of a couple of classes in memory is a really big worry, I think you really need to be reconsidering your architecture.

@pjfanning
Copy link
Member

The ReadOnlyClassToSerializerMap instance lifecycle should closely match the SerializerCache lifecycle and the SerializerCache should be GCable after you dereference the ObjectMapper instance that it relates to.

@cowtowncoder
Copy link
Member

Yes, the remaining retention is wrt Serializer caching & makes sense since there are typically many more serialized value types (as it's the exact runtime type vs statically declared for deserialization).
And to drop those caches it is necessary to drop ObjectMapper (and ObjectWriters created from one, if any, but they are usually one-offs being light-weight).

@dylan-tao
Copy link
Author

@pjfanning @cowtowncoder yeah solved, solution read and write locks control the lifecycle of an ObjectMapper instance, class descriptions and instance references will be recycled, thanks!

@cowtowncoder
Copy link
Member

Created FasterXML/jackson-databind#4659 to address this for Jackson 3.0 -- TypeFactory life-cycle should be bound to individual ObjectMapper to avoid having to trigger clearCacheson global defaultTypeFactory` instance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants