Java – classloader will not be garbage collected even if there is no GC root

We have one in GlassFish v2 Complex applications running under 1.1 In order to dynamically load our code, we implement a customclassloader, which can redefine classes

This works well. Except after reloading the same class several times (so a new customclassloader is created each time), we get a permgen space error because other instances of customclassloader are not garbage collected (this class should have only one instance)

I tried different ways to track the location of the leak:

>Visual VM = > I dump the heap and extract all instances of customclassloader I can see that none of them is final When I check the nearest GC root, visualvm tells me no (except for the last instance, because it is' real 'used). > Jmap / jhat = > it gives me almost the same result: I see all instances of customclassloader, and then when I click the link to view the reference location of one of them, I get a blank page, which means there is no... > eclipse memory analyzer tool = > when I run the following OQL query, I get a strange result: select c from instanceof my package. Customclassloader C has only one result, indicating that only one instance is obviously incorrect

I also checked the link and realized some resource release when creating a new customclassloader, but there was no change: permgen memory was still increasing

So I may have missed something. The difference between points (1-2) and (3) shows something I don't understand Where can I learn what is wrong? Since all the tutorials I followed showed how to use the "search recent GC root" function to search for leaked references (not in my case), I don't know how to track errors

Editor 1: I uploaded an example of heap dump here You can select an unloaded classloader in visual VM using the following query: select s from saierp core. framework. system. Saitaskclassloader s can see that there are four instances, and the third instance should have been collected, because there is no GC root... There must be a reference, but I don't know how to search it Any hint is welcome:)

Editor 2: after some more in - depth tests, I saw a very strange pattern The leak seems to depend on the data openjpa is loading: if no new data is loaded, the classloader can be GCed, otherwise it is not Here is the code I used when I created a new saitaskclassloader to "clean up" the old code:

PCRegistry.deRegister(cl);
LogFactory.release(cl);
ResourceBundle.clearCache(cl);
Introspector.flushCaches();

=Mode 1 (class loader GCed):=

>New saitaskclassloader > load data D1, D2,..., DN > New saitaskclassloader > load data D1, DN >

=Mode 2 (class loader not GCed):=

>New saitaskclassloader > load data D1, D3 > New saitaskclassloader > load data D3, D4, D5 > New saitaskclassloader > load data D5, D6, D7 >

In all cases, the cleared saitaskclassloader has no GC root We are using openjpa 1.2 one

Thank you & best wishes

Solution

Without fragments of customclassloader source code or actual heap dumps, it is difficult to find the problem Your customclassloader cannot be a singleton If so, your design won't work (or I missed something)

You need to get a list of classloader instances of customclassloader type and track references to these objects

These posts can help you further analyze it and enter the hint of secretly pursuing classloader leakage:

> Debugging Dynamic ClassLoaders in Heap Dumps > How to analyze leaky web-apps > A couple of typical causes of ClassLoader leaks

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>