1

This is a high-voted example of memory leak from StackOverflow:

Not unloading Singletons when bringing down a Java EE application. Apparently, the Classloader that loaded the singleton class will retain a reference to the class, and hence the singleton instance will never be collected. When a new instance of the application is deployed, a new class loader is usually created, and the former class loader will continue to exist due to the singleton.

1) I do not understand how can I "unload" a singleton and what is meant by "bringing down a Java EE application". Could you provide code examples (wrong and right code samples) and scenarios?

2) From the same stackoverflow post:

Take any web application running in any servlet container (Tomcat, Jetty, Glassfish, whatever...). Redeploy the app 10 or 20 times in a row (it may be enough to simply touch the WAR in the server's autodeploy directory.

Unless anybody has actually tested this, chances are high that you'll get an OutOfMemoryError after a couple of redeployments, because the application did not take care to clean up after itself. You may even find a bug in your server with this test.

The problem is, the lifetime of the container is longer than the lifetime of your application. You have to make sure that all references the container might have to objects or classes of your application can be garbage collected.

If there is just one reference surviving the undeployment of your web app, the corresponding classloader and by consequence all classes of your web app cannot be garbage collected.

Threads started by your application, ThreadLocal variables, logging appenders are some of the usual suspects to cause classloader leaks.

I cannot understand how is it possible that container (Tomcat classes/objects) holds references to objects or classes of my application and it is my fault. Automatic memory management means I don't have to care about freeing memory, right? So what shall I take care of if my application runs within Tomcat or another container?

Code Complete
  • 3,146
  • 1
  • 15
  • 38
  • It's basically the same scenario that is described in the top answer. This quote actually misses the crucial part which is where a reference to the singleton is kept except in the classloader (a ThreadLocal, for example). – RealSkeptic Jan 01 '19 at 14:57
  • I updated my answer. Probably still pretty unspecific, but maybe hopefully good enough to accept. I also really doubt that much else will be coming in here ... – GhostCat Jan 11 '19 at 14:05

1 Answers1

1

A single jvm can be used as "application server". It hosts containers, coming in as "packages" (EAR or WAR files for example) that can be dynamically added / removed from the jvm.

You achieve that by using the capabilities of the class loader. But a class loader keeps track of all the classes it loaded. So, to free up the old class loader it has to forget all classes it knows about. But it can't for singletons done wrong.

Or quoting from IBM:

An object retains a reference to the class it is an instance of. A class retains a reference to the class loader that loaded it. The class loader retains a reference to every class it loaded. Retaining a reference to a single object from a web application pins every class loaded by the web application. These references often remain after a web application reload. With each reload, more classes are pinned which leads to an out of memory error

By request from the OP, I tried to find examples for "bad" respectively "working" singleton implementations, but I couldn't find any.

But to give a different perspective: since we have enums, we can use enums to implement a singleton (see here). So, probably the reasonable answer today is: simply use enums. And given the fact that there isn't much to find on the internet regarding this subject, my (personal) gut feeling is: this is simply not a relevant problem in the real world (any more).

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • I would appreciate an example of such a wrong singleton causing a memory leak very much. If you'd attached such example to the answer, I would definitely select it! – Code Complete Jan 03 '19 at 21:14