You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Michal Botka <mr...@gmail.com> on 2014/02/06 21:13:11 UTC

Tomcat classloader memory leak when an object is stored into session

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

Re: Tomcat classloader memory leak when an object is stored into session

Posted by Leon Rosenberg <ro...@gmail.com>.
On Fri, Feb 7, 2014 at 12:45 AM, Caldarale, Charles R <
Chuck.Caldarale@unisys.com> wrote:

> > From: Leon Rosenberg [mailto:rosenberg.leon@gmail.com]
> > Subject: Re: Tomcat classloader memory leak when an object is stored
> into session
>
> > > 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.
>
> > I think the OP states, that this shouldn't be the case.
>
> > Personally I'm struggling with this one. But since I don't use the
> > reloading anyway I will relax and wait for enlightenment that is sure to
> > come from Chuck ;-)
>
> Since you insist...
>

Thank you!
I knew we can always count on you (now seriously) ;-)

best regards
Leon


>
> Start with the Wiki:
> http://wiki.apache.org/tomcat/MemoryLeakProtection
>
>  - Chuck
>
>
> THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY
> MATERIAL and is thus for use only by the intended recipient. If you
> received this in error, please contact the sender and delete the e-mail and
> its attachments from all computers.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>

RE: Tomcat classloader memory leak when an object is stored into session

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Leon Rosenberg [mailto:rosenberg.leon@gmail.com] 
> Subject: Re: Tomcat classloader memory leak when an object is stored into session

> > 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.

> I think the OP states, that this shouldn't be the case.

> Personally I'm struggling with this one. But since I don't use the
> reloading anyway I will relax and wait for enlightenment that is sure to
> come from Chuck ;-)

Since you insist...

Start with the Wiki:
http://wiki.apache.org/tomcat/MemoryLeakProtection

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat classloader memory leak when an object is stored into session

Posted by Leon Rosenberg <ro...@gmail.com>.
On Thu, Feb 6, 2014 at 11:58 PM, David Kerber <dc...@verizon.net> wrote:

> On 2/6/2014 3:13 PM, Michal Botka wrote:
>
>> 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.
>>
>
> This is true.  What is your question?


I think the OP states, that this shouldn't be the case.

Personally I'm struggling with this one. But since I don't use the
reloading anyway I will relax and wait for enlightenment that is sure to
come from Chuck ;-)

regards
Leon

Re: Tomcat classloader memory leak when an object is stored into session

Posted by Leon Rosenberg <ro...@gmail.com>.
On Fri, Feb 7, 2014 at 8:38 AM, Michal Botka <mr...@gmail.com> wrote:

> Is there a way how to avoid this leak?
> I would like to develop an application which can be safely
> deployed/undeployed without restarting the server.
> OK, now I know that my application cannot store it's objects into
> session, but that is very strong requirement which the most of the
> applications don't meet.
> Thanks for help.
>

But do you have to serialize your sessions? Switching off session
serialization might help.
regards
Leon


>
> 2014-02-06 22:58 GMT+01:00 David Kerber <dc...@verizon.net>:
> > On 2/6/2014 3:13 PM, Michal Botka wrote:
> >>
> >> 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.
> >
> >
> > This is true.  What is your question?
> >
> >
> >
> >>
> >> 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
> >>
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> > For additional commands, e-mail: users-help@tomcat.apache.org
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>

Re: Tomcat classloader memory leak when an object is stored into session

Posted by Michal Botka <mr...@gmail.com>.
On 07/02/2014, Mark Thomas wrote:

> There is no leak.
...

Hello Mark,
thank you very mych for help and your great presentation. You were
absolutely right, there was no memory leak :-)
Obviously there was a different issue in my application causing the leak...
I'm sorry for spamming.
Best regards
Michal

P.S. Regarding the WebappClassLoader instances I'm suprised that there
is quite often an instance with started=false remaining after garbage
collection is performed. However, this instace is collected later as
the used perm gen memory is reaching the maximum.

2014-02-07 11:46 GMT+01:00 Mark Thomas <ma...@apache.org>:
> On 07/02/2014 06:38, Michal Botka wrote:
>> Is there a way how to avoid this leak?
>
> There is no leak.
>
>> I would like to develop an application which can be safely
>> deployed/undeployed without restarting the server.
>
> That is very much under your control. I'd suggest reading this:
> http://people.apache.org/~markt/presentations/2010-08-05-Memory-Leaks-JavaOne-60mins.pdf
>
> as it highlights much of what can go wrong.
>
>
>> OK, now I know that my application cannot store it's objects into
>> session, but that is very strong requirement which the most of the
>> applications don't meet.
>
> There is no such requirement. Storing objects in the session does not
> trigger a memory leak on web application reload.
>
>> Thanks for help.
>>
>> 2014-02-06 22:58 GMT+01:00 David Kerber <dc...@verizon.net>:
>>> On 2/6/2014 3:13 PM, Michal Botka wrote:
>>>>
>>>> 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.
>>>
>>>
>>> This is true.  What is your question?
>
> No, this is not true.
>
>>>> To illustrate the issue, you can find an example below.
>>>> Thanks in advance :-)
>
> I've taken the provided test code and confirmed - with a profiler - that
> there is no memory leak.
>
> There is something else that is triggering your memory leak. Follow the
> steps in the presentation above to find out exactly what it is that is
> pinning the web application class loader in memory.
>
> Mark
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat classloader memory leak when an object is stored into session

Posted by Mark Thomas <ma...@apache.org>.
On 07/02/2014 06:38, Michal Botka wrote:
> Is there a way how to avoid this leak?

There is no leak.

> I would like to develop an application which can be safely
> deployed/undeployed without restarting the server.

That is very much under your control. I'd suggest reading this:
http://people.apache.org/~markt/presentations/2010-08-05-Memory-Leaks-JavaOne-60mins.pdf

as it highlights much of what can go wrong.


> OK, now I know that my application cannot store it's objects into
> session, but that is very strong requirement which the most of the
> applications don't meet.

There is no such requirement. Storing objects in the session does not
trigger a memory leak on web application reload.

> Thanks for help.
> 
> 2014-02-06 22:58 GMT+01:00 David Kerber <dc...@verizon.net>:
>> On 2/6/2014 3:13 PM, Michal Botka wrote:
>>>
>>> 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.
>>
>>
>> This is true.  What is your question?

No, this is not true.

>>> To illustrate the issue, you can find an example below.
>>> Thanks in advance :-)

I've taken the provided test code and confirmed - with a profiler - that
there is no memory leak.

There is something else that is triggering your memory leak. Follow the
steps in the presentation above to find out exactly what it is that is
pinning the web application class loader in memory.

Mark


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat classloader memory leak when an object is stored into session

Posted by Mark Thomas <ma...@apache.org>.
Michal Botka <mr...@gmail.com> wrote:
>Is there a way how to avoid this leak?
>I would like to develop an application which can be safely
>deployed/undeployed without restarting the server.
>OK, now I know that my application cannot store it's objects into
>session, but that is very strong requirement which the most of the
>applications don't meet.

The leak, as described, should not happen.

The sessions are serialized to disk. That disconnects the objects in the session from the web application class loader. When they are deseralized it will be with the class loader of the new web application.

Therefore, objects in the session should not be retaining references to the old web application class loader.

I need to run through the provided test case to see if there is something going wrong but at this point I strongly suspect that the source of the leak is something else entirely (most likely a leak in a 3rd party library or possibly an application bug).

Mark


>Thanks for help.
>
>2014-02-06 22:58 GMT+01:00 David Kerber <dc...@verizon.net>:
>> On 2/6/2014 3:13 PM, Michal Botka wrote:
>>>
>>> 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.
>>
>>
>> This is true.  What is your question?
>>
>>
>>
>>>
>>> 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
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: users-help@tomcat.apache.org
>>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>For additional commands, e-mail: users-help@tomcat.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat classloader memory leak when an object is stored into session

Posted by Michal Botka <mr...@gmail.com>.
Is there a way how to avoid this leak?
I would like to develop an application which can be safely
deployed/undeployed without restarting the server.
OK, now I know that my application cannot store it's objects into
session, but that is very strong requirement which the most of the
applications don't meet.
Thanks for help.

2014-02-06 22:58 GMT+01:00 David Kerber <dc...@verizon.net>:
> On 2/6/2014 3:13 PM, Michal Botka wrote:
>>
>> 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.
>
>
> This is true.  What is your question?
>
>
>
>>
>> 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
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat classloader memory leak when an object is stored into session

Posted by David Kerber <dc...@verizon.net>.
On 2/6/2014 3:13 PM, Michal Botka wrote:
> 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.

This is true.  What is your question?


>
> 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
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org