When an application stores an object into the session and then the
application is reloaded using Tomcat Web Application Manager, the
classloader cannot be garbage collected. As a result, the
"OutOfMemoryError: PermGen space" error occurs after several reloads.
To illustrate the issue, you can find an example below.
Thanks in advance :-)
1. The EvilClass class whose instances are stored into the session:
public class EvilClass implements Serializable {
// Eat 100 MB from the JVM heap to see that the class is not
garbage collected
protected static final byte[] MEM = new byte[100 << 20];
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
2. Servlet which stores EvilClass instances into session
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse
resp) throws ServletException, IOException {
EvilClass obj = new EvilClass();
obj.setValue(req.getRequestURI());
req.getSession().setAttribute("test", obj);
getServletContext().log("Attribute stored to session " + obj);
}
}
3. web.xml part which maps the servlet to an URL
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>test.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Steps to reproduce the issue:
1. Copy application WAR to the webapps directory.
2. Start Apache Tomcat.
3. Hit TestServlet.
4. Check Heap/PermGen size using Java VisualVM.
5. Reload the application thru Tomcat Web Application Manager.
6. Hit TestServlet again.
7. Perform GC and check Heap/PermGen size again.
Environment:
Apache Tomcat version: 7.0.50
OS: Windows 7 64
JVM: Java HotSpot(TM) 64-Bit Server VM (23.6-b04, mixed mode)
Java: version 1.7.0_10, vendor Oracle Corporation