https://bz.apache.org/bugzilla/show_bug.cgi?id=58023
Bug ID: 58023
Summary: Memory Leak in WebappClassLoader
Product: Tomcat 7
Version: 7.0.59
Hardware: PC
Status: NEW
Severity: normal
Priority: P2
Component: Catalina
Assignee: [email protected]
Reporter: [email protected]
Memory leak occur because a reference of entry.manifest is never removed.
Problem:
1 - ${class}.class.getResource( ${resource.name1} );
2 - JarFile load a manifest.
3- resourceEntries put a new ResourceEntry with a manifest reference.
4 - ${class}.class.getResource( ${resource.name2} );
5 - resourceEntries put a new ResourceEntry with a manifest reference. Manifest
contains ~20MB, but, no problem because the JarFile is the same reference. In
other words, only one Manifest in the Heap space.
6 - wait for 90000 milliseconds.
7 - ${class}.class.getResource( ${resource.name3} );
8 - WebappClassLoader.closeJARs because time is elapsed 90000 milliseconds and
load a new JarFile instances.
9 - JarFile load a new manifest.
10 - resourceEntries put a new ResourceEntry with a new manifest reference.
11 - wait for 90000 milliseconds
...
And this will be memory leak in little time (See resourceEntries.png).
In attachment, a scenario to simulate this problem.
PS.: A jar file need to be signed for accelerate leak, because of
Manifest.entries ~5MB (see manifests.png) retained heap (in test case, but, my
real app is ~20MB).
I attached the heap dump used in this test case (heap.zip).
Solution:
Always release the manifest reference.
Workaround:
public class WebappClassLoader
extends
org.apache.catalina.loader.WebappClassLoader
{
@Override
public InputStream getResourceAsStream( String name )
{
InputStream in = super.getResourceAsStream( name );
ResourceEntry entry = resourceEntries.get( name );
if ( entry != null )
{
// prevent a memory leak
entry.manifest = null;
entry.certificates = null;
}
return in;
}
@Override
public URL getResource( String name )
{
URL url = super.getResource( name );
ResourceEntry entry = resourceEntries.get( name );
if ( entry != null )
{
// prevent a memory leak
entry.manifest = null;
entry.certificates = null;
}
return url;
}
}
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]