Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a true singleton in java?

I am facing a problem with my singleton when used across multiple class loaders. E.g Singleton accessed by multiple EJBs. Is there any way to create a singleton which has only one instance across all class loader?

I am looking for pure java solution either using custom class loader or some other way.

like image 258
rjoshi Avatar asked Sep 29 '09 21:09

rjoshi


People also ask

How is a singleton created in Java?

To create a singleton class, a class must implement the following properties: Create a private constructor of the class to restrict object creation outside of the class. Create a private attribute of the class type that refers to the single object.

What is the best way to implement singleton in Java?

The most popular approach is to implement a Singleton by creating a regular class and making sure it has: A private constructor. A static field containing its only instance. A static factory method for obtaining the instance.

What is true about the Singleton pattern?

This pattern involves a single class which is responsible to create an object while making sure that only single object gets created. This class provides a way to access its only object which can be accessed directly without need to instantiate the object of the class.


3 Answers

The only way would be to make your singleton class be loaded by a single classloader - put that jar file in the bootclasspath, for example.

A static variable is inherently tied to the classloader which loaded the class containing that variable. It's just the way it works. If you need absolutely one instance, you need that class to only be loaded by one classloader.

like image 118
Jon Skeet Avatar answered Oct 18 '22 06:10

Jon Skeet


JavaEE app servers generally solve this problem by setting up the singleton as a "service", the exact definition and configuration of which depends on the appserver in question.

For example, in JBoss you could use a xyz-service.xml descriptor to set up a singleton object that hangs off the JNDI or JMX tree, and your application components (e.g. your EJBs) would fetch the singleton from the tree. That protects you to some extent from the underlying classloader semantics.

like image 30
skaffman Avatar answered Oct 18 '22 08:10

skaffman


J2EE is designed with clustering in mind, so any designs that it supports are going to have to work with multiple JVM's. I take it from your question that you aren't concerned about a clustered environment, so a simple insertion into JNDI on your app server should do it. In Glassfish, that is called a lifecycle listener. After the startup even, insert your singleton into JNDI, and then have everything else do a JNDI lookup to find it.

Note that GlassFish could still mess you up here, in that it could serialize the class to JNDI causing you to get different instances. I doubt it actually does this within one JVM, but you won't know until you try it.

The real bottom line answer is that J2EE is hostile to a global true singleton, and the J2EE way around the problem is to rethink the solution. Something like a database to hold values or some other external service that can ensure that only one instance of the data (even if multiple instances of objects representing the data) exists is the J2EE way.

like image 39
Yishai Avatar answered Oct 18 '22 06:10

Yishai