'UnmarshallerImpl finalize() method leads to memory leak
I'm using webServiceTemplate in my multithread Spring app. There are my jaxb dependencies:
compile('javax.xml.bind:jaxb-api:2.3.0')
compile('org.glassfish.jaxb:jaxb-runtime:2.3.0')
My application makes a lot esb requests and how I have noticed for each request/response (marshalSendAndReceive) jaxb creates an instance of UnmarshallerImpl which implements finalize() method and this is the problem for me, because objects creates faster than Finalizer thread can handle this objects, so it leads to memory leak. I'm wondering why do glassfish implementation still has finalize() in UnmarshallerImpl, it really creates problems for me. Is there any alternative versions of glassfish jaxb implementation or similar libraries? I will be grateful for any useful information.
UPD: I have also tried version 3.0.2 of jaxb:jaxb-runtime - the problem is still present
Solution 1:[1]
I think your best bet in the long term is to switch to processing your requests using an XML streaming implementation.
In the short term ...
- As you noted, the JAXB reference implementation still uses
finalize()in the latest release. - I don't think there is a way to increase the number of GC finalizer threads. (That is probably a good thing ....)
- This Q&A lists some alternative JAXB implementation: List of JAXB providers
- Since it is open source, you could modify the
finalize()implementation for theUnmarshallerImplyou are currently using.
The standard implementation of the finalize() method looks like this:
@Override
@SuppressWarnings("FinalizeDeclaration")
protected void finalize() throws Throwable {
try {
ClassFactory.cleanCache();
} finally {
super.finalize();
}
}
Thinking about it ... you may be able to get away with not cleaning the ClassFactory cache every time an UnmarshallerImpl instance is garbage collected. Maybe this could just set a "global" flag to tell an asynchronous cache cleaner that there is work to do.
Of course, there is a maintenance overhead in using a modified library in the longer term, so it would be advisable to try to get your changes accepted by the upstream project.
UPDATE
I should have looked at cleanCache earlier, but it appears that all it does is to drop a map that has been cached in a thread-local. This should be cheap, and shouldn't be a source of contention. Also, it means that doing this asynchronously (i.e. on a different thread!) won't be effective. (It also means that the Cleaner approach suggested below won't work either.)
The other alternative is to not to call cleanCache at all, but that gives us a potential memory leak via the thread local!!
Either way, I am (now!) puzzled that this finalize() method is a bottleneck at all. Are you sure that the problem isn't caused by a different one?
I'm wondering why do glassfish implementation still has
finalize()inUnmarshallerImpl, it really creates problems for me.
The answer is obvious. They haven't gotten around to1 fixing it yet.
1 - Rhetorical questions: 1) How much money are you paying for support for your GlassFish implementation? 2) There are things called "open source bounties". Have you tried offering one to get this problem fixed?
Solution 2:[2]
The finalize() method is currently deprecated, because it didn’t work as it supposed to. You have to use methods like System.gc() to finalize classes or else it wouldn’t work.
Discussion: Why is the finalize() method deprecated in Java 9?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | engine |
