问题
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.
回答1:
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.
回答2:
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.
回答3:
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.
回答4:
To achieve TRUE Singleton
, you have follow below guidelines:
- Make your class as
final
. Others can't sub-class it and create one more instance - Make your Singleton instance as
private static final
- Provide
private constructor
andpublic getInstance()
method. - Make sure that this
Singleton
class is loaded byone ClassLoader only
- override
readResolve()
method and return same instance without creating new instance in de-Serialization process.
Sample code:
final class LazySingleton {
private LazySingleton() {}
public static LazySingleton getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final LazySingleton INSTANCE = new LazySingleton();
}
private Object readResolve() {
return LazyHolder.INSTANCE;
}
}
Refer to below SE question for more details:
What is an efficient way to implement a singleton pattern in Java?
来源:https://stackoverflow.com/questions/1494957/how-to-create-a-true-singleton-in-java