Absolute Singleton. Not Really...

Singleton are not true singleton and there are many reasons: One of them is multiple class loaders can have their own copy of singleton. See How single can your singleton instance be?. I started googling for true singleton and came across Absolute Singleton.

When I use this approach in my product, it didn't work instead it was throwing exception java.lang.ClassNotFoundException on the Singleton class.

java.lang.ClassNotFoundException: com.example.common.utils.JCSCache at com.sun.enterprise.util.ConnectorClassLoader.loadClass(ConnectorClassLoader.java:222)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at com.example.common.utils.JCSCache.getInstance(JCSCache.java:131)


After looking at the exception and class initialization, I found that what happens if the first instance is initiated by custom class loader and not the default one?

It will not find an existing instance because while creating the instance, due to custom class loader, it will go into "if (! myClassLoader.toString().startsWith("sun.")) {" (see the Absolute Singleton) condition and try to find existing instance instead of creating new which doesn't exits yet so it throws the java.lang.ClassNotFoundException.

The work around I found is to catch the exception and create the instance of AbsoluteSingleton class.

But next time, custom class loader try to get the instance, again it's not going to find it and create it's own instance.
See the below log.

First instance of JCSCache ( com.example.common.utils.JCSCache@124adaf) created by class loader: org.glassfish.openesb.pojose.jbi.su.SUClassLoader@1b78d60
and

2nd instance (com.example.common.utils.JCSCache@1a859dc) is created by EJBClassLoader.

So Absolute singleton is not really absolute singleton.

[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ENTRY] -->getInstance()
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | DEBUG] Class Loader:org.glassfish.openesb.pojose.jbi.su.SUClassLoader@1b78d60
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ERROR] Exception:com.example.common.utils.JCSCache
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ENTRY] -->JCSCache()
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | DEBUG] JCSCache constructor called.
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | EXIT] <--JCSCache() [2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | ENTRY] -->init()
[2009-09-27 21:56:04,713 | Thread-79 | common.utils.JCSCache | DEBUG] Setting the cache configuratio name:/cache.ccf
[2009-09-27 21:56:04,721 | Thread-79 | common.utils.JCSCache | DEBUG] Initializing region base cache objects.
[2009-09-27 21:56:04,786 | Thread-79 | common.utils.JCSCache | EXIT] <--init() true [2009-09-27 21:56:04,786 | Thread-79 | common.utils.JCSCache | EXIT] <--getInstance() com.example.common.utils.JCSCache@124adaf

2nd instance:

2009-09-27 21:56:06,812 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ENTRY] -->getInstance()
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] Class Loader:EJBClassLoader :
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ERROR] Exception:com.example.common.utils.JCSCache
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ENTRY] -->JCSCache()
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] JCSCache constructor called.
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | EXIT] <--JCSCache() [2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | ENTRY] -->init()
[2009-09-27 21:56:06,813 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] Setting the cache configuratio name:/cache.ccf
[2009-09-27 21:56:06,818 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | DEBUG] Initializing region base cache objects.
[2009-09-27 21:56:06,926 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | EXIT] <--init() true [2009-09-27 21:56:06,926 | httpSSLWorkerThread-8080-0 | common.utils.JCSCache | EXIT] <--getInstance() com.example.common.utils.JCSCache@1a859dc

No comments: