I have a simple singleton class in Java that looks like the following one:
public class Singleton{
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){
if (instance == null){
instance = new Singleton();
}
return instance;
}
public void doSomething(){
...
}
}
My code also contains two classes, from now on called A and B, that both have the following structure:
public class Foo{
...
public void bar(){
...
Singleton.getInstance().doSomething();
...
}
...
}
During an execution the code in class A is executed first and therefore it silently instantiates the singleton instance. However, later on when B's code gets executed, the singleton instance is instantiated again, which is not what I want to achieve.
After a little investigation we found that class A and B use a different class loader, which means the singleton class is also loaded twice, resulting into two singleton instances.
I've looked for solutions to this issue on the web and found several (quite similar) pages, e.g. http://www.javaworld.com/article/2073352/core-java/simply-singleton.html?page=2 and http://snehaprashant.blogspot.nl/2009/01/singleton-pattern-in-java.html.
However, after trying out several options I still can't get it to work, mainly because I don't really know how to apply the solution(s) in the simple code listed above.
So my question is: can someone provide me with a (clue to a) practical solution for my code to the problem described above so that the singleton is only instantiated once regardless of the classloader being used?
I doubt the solution in the JavaWorld article works. getContextClassLoader(), and Singleton.class.getClassLoader() can return different classloaders each time. And if you got a consistent classloader, then the only way to use the class would be via reflection.
I guess they expect you to replace:
Singleton.getInstance().doSomething();
with:
try {
Object instance = getClass("package.Singleton").getMethod("getInstance").invoke(null);
instance.getClass().getMethod("doSomething").invoke(instance);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
Instead, I would look at why there are multiple classloaders. Either keep all your code under the same classloader, or put the singleton into a common parent of both classloaders, and make the class unavailable to the child classloaders.
Related
I saw answers like these, tried to clarify via comments, and was unsatisfied by examples here.
Maybe it's time for this specific question...
Why enum singleton implementation is called lazy?
public enum EnumLazySingleton {
INSTANCE;
EnumLazySingleton() {
System.out.println("constructing: " + this);
}
public static void touchClass() {}
}
How it is different from eager implementation?
public class BasicEagerSingleton {
private static final BasicEagerSingleton instance = new BasicEagerSingleton();
public static BasicEagerSingleton getInstance() {
return instance;
}
private BasicEagerSingleton() {
System.out.println("constructing: " + this);
}
public static void touchClass() {}
}
Both will init instance without accessing INSTANCE/getInstance() - e.g. call touchClass().
public class TestSingleton {
public static void main(String... args) {
System.out.println("sleeping for 5 sec...");
System.out.println("touching " + BasicEagerSingleton.class.getSimpleName());
BasicEagerSingleton.touchClass();
System.out.println("touching " + EnumLazySingleton.class.getSimpleName());
EnumLazySingleton.touchClass();
}
}
Output:
sleeping for 5 sec...
touching BasicEagerSingleton
constructing: BasicEagerSingleton#7bfcd12c
touching EnumLazySingleton
constructing: INSTANCE
Now, we can say both are lazy. What is eager then?
It is clear how (e.g) "double-checked locking" way is actually lazy (and messy, and slow). But if enum is lazy, then any singleton is lazy due to inevitable class loading - in fact, everything is lazy. At which point will this distinction stop making any sense?
The first two linked answers (by Peter Lawrey and Joachim Sauer) both agree that enums are not lazily initialized. Answers in the third link are simply wrong about what lazy initialization means.
The recommendation to use enums as singletons originates from Josh Bloch's Effective Java. Notably, the chapter on enum singletons makes no mention of laziness. There is a later chapter dedicated to lazy initialization, that likewise makes no mention of enums. The chapter contains two highlights.
If you need to use lazy initialization for performance on a static field, use the lazy initialization holder class idiom.
If you need to use lazy initialization for performance on an instance field, use the double-check idiom.
Undoubtedly, enums would be another idiom on this list if they were in any way lazily initialized. In fact they are not, although confusion about the meaning of lazy initialization results in some incorrect answers, as the OP shows.
May I wager the following:
You are trying to identify 2 "processes" or ... "things" (let's make this easy to understand - because if I start saying "Code Blocks", it sounds more difficult)...
At some point the class-loader will run, and you would like to know what "things" will be executed when the class-loader loads a class.
At another point invoking a method on the class will cause another "thing" to run / execute, and you would like to know which, exactly, (which "processes") would start..
The following facts are relevant:
Static initializers are run when the class-loader loads the class. The class-loader will not load the class until the code that is
running encounters the need to load it (because a method or field has
been invoked) such as: touchClass()
If a singleton instance of EITHER a class, OR an enumerated type has a field that is being initialized in the static
part of the class it will be loaded as soon as you 'touch' the
class - because the Class-Loader runs all static initializations for a class or enum on loading.
Lazy loading, likely, (And this is my "interpretation" about what you are asking) would happen when a method invokation asks the class
to create a singleton instance - which could happen quite a bit of
time after the "loading" of the class or enum.
A class like the following:
public class LazySingleton
{
// At time of class-loading, this singleton is set to 'null'
private static singleton = null;
// This is a method that will not be invoked until it is called by
// some other code-block (some other "thing")... When "touchClass()"
// is called, the singleton instance is not created.
public static LazySingleton retrieveSingleton()
{
if (singleton == null) singleton = new LazySingleton();
return singleton;
}
// DOES NOTHING... The Singleton is *not* loaded, even though the
// Class Loader has already loaded this Java ".class" file
// into memory.
public static void touchClass() { }
private LazySingleton()
{ System.out.println("constructing: LazySingleton"); }
}
Here on the other hand:
public enum EagerEnum
{
// The class loader will run this constructor as soon as this 'enum'
// is loaded from a '.class' file (in JAR or on disk) into memory
MyEnumConstant();
private EagerEnum()
{ System.out.println("Eager Enum Constructed"); }
// This will cause the Class Loader to Load this enum from the
// Java ".class" File immediately, and the "MyEnumConstant" will
// also have to be loaded - meaning the constructor will be called.
public static void touchEnum() { }
}
So the following code would produce the output
LazySingleton.touchClass(); // Prints nothing
EagerEnum.touchClass(); // Prints "Eager Enum Constructed"
LazySingleton.getSingletonInstance(); // Prints "constructing: LazySingleton
I've got interface 'FileFactory' with 'produce' method.
This interface is implemented by two classes: 'SingleFileFactory' and 'MultipleFileFactory'.
Both of these classes have the same code structure but returning different injected object.
IntelliJ prints infirmation, that code in both classes is duplicated.
I can't paste original code, so it's an example
Example:
public class SingleFileFactory {
#Inject
private FiirstSingleFile firstSingleFile;
#Inject
private SecondSingleFile secondSingleFile;
public File produce() {
if(something)
return firstSingleFile;
else
return secondSingleFile;
}
}
Class 'MultipleFileFactory' has the same logical but different injected objects.
I wanted to separate code into multiple classes, because in my opinion each can return specific object in the result.
Do you know how to avoid such as duplication - should I stretch it and pack into one class with a lot of injects and if expressions?
Maybe you have better solution for this problem.
I have this monolithic Java-Application that I want to port to newer techniques and I want to apply Scala wherever it makes sense.
Now I translated a rather huge java-singleton class implementation to a Scala object.
In another class I used to do this (JAVA):
public class MyOtherClass
{
protected MyClass myClass;
public MyOtherClass()
{
myClass = MyClass.getInstance();
}
}
Now I'd like to do the following:
public class MyOtherClass
{
protected MySCALAClass myClass;
public MyOtherClass()
{
myClass = MySCALAClass$.MODULE$;
}
}
But this doesn't work. It says:
Required MyScalaClass, Found MyScalaClass$
I also tried to create a small function
def getInstance() = this
but of course this yields the same problem.
Any ideas? I have searched this topic and I see how it is not a problem if you just want to call the methods of the object, but I would need to rewrite many, many calls to the "myClass"-object to even test this.
edit: I'm fully aware that I could rename every call to "myClass" to "MySCALAClass", but that is no real fix, just a workaround and it is tedious for a big project.
I think #neuronaut 's comment is correct.
See following questions:
Scala object MODULE$
Singletons as Synthetic classes in Scala?
The singleton class (MySCALAClass$ in your case) is not a subclass of the original class (MySCALAClass) and so the singleton object (MySCALAClass$.MODULE$) is not an instance of it either.
E.g I have class Singleton with static field instance:
public class Singleton {
private static Singleton instance;
// other code, construct, getters, no matter
}
I can load this class twice with two different classloaders. How could I avoid it? It is unsafe and dangerous.
Also, if I set instance to null, would it set to null for both classes?
Singleton singleton = Singleton.getInstance();
singleton = null;
If you want a true Singleton across classloaders, then you need a common parent to load the class in question, or you need to specify the classloader yourself.
Update: From the comment from #Pshemo below a fair bit of the content in the blog below might come directly from a JavaWorld Article. I've left the blog entry in as it may still help someone, but its worth knowing where the content originally came from.
Original:
There is a blog entry that gives you a way to do this" (although I havent tried it!), and it looks fairly reasonable
As requested below here a code snippet from my link above - I do suggest you visit the blog though for the full context:
private static Class getClass(String classname) throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if(classLoader == null)
classLoader = Singleton.class.getClassLoader();
return (classLoader.loadClass(classname));
}
This is a hack misusing the fact that Properties extends Map, an old unfortunate design decision.
public final class JvmWideSingleton
{
private static final JvmWideSingleton INSTANCE;
static {
// There should be just one system class loader object in the whole JVM.
synchronized(ClassLoader.getSystemClassLoader()) {
Properties sysProps = System.getProperties();
// The key is a String, because the .class object would be different across classloaders.
JvmWideSingleton singleton = (JvmWideSingleton) sysProps.get(JvmWideSingleton.class.getName());
// Some other class loader loaded JvmWideSingleton earlier.
if (singleton != null) {
INSTANCE = singleton;
}
else {
// Otherwise this classloader is the first one, let's create a singleton.
// Make sure not to do any locking within this.
INSTANCE = new JvmWideSingleton();
System.getProperties().put(JvmWideSingleton.class.getName(), INSTANCE);
}
}
}
public static JvmWideSingleton getSingleton() {
return INSTANCE;
}
}
This could be made parametrized, but then the initialization would be lazy and go to getSingleton().
Properties is Hashtable-based, so it is thread safe (as per the documentation). So one could use props.computeIfAbsent(). But I like it this way more.
Also read here: Scope of the Java System Properties
I just wrote it and there is a chance there's something I overlooked that would prevent this from working.
Initialize a singleton by configure file is suitable or not?
I notice that the constructor of singleton should not have any parameter, the reason is that if you need use parameters to configure your object, probably that should not be singleton. Seems this sentence very famous, but indeed there are serval cases are special:e.g.
We design a simple distributed system to deal with tons of users' query:
only one central server
n sub servers, each sub server connecting to central server
there is no connections between sub servers
Obviously, we may design the "central server" as singleton, the details like this:
enum ServerType;
abstract class Server;
class CentralServer inherit from Server;(CentralServer is singleton)
class SubServer inherit from Server;
class Query;
... ... ...
But the central server need some configuration, such as:
serverName
description
portNum-ipAddress map
the list of its sub servers
the size of BlockingQueue
... ... ...
How to initialize the central server by these properties?
My current solution:
using the configure file to finish this part job.
I define another class called Configuration.
So the current constructor of central server like this:
class CentralServer extends Server implements Runnable, ....... {
....
....
private static CentralServer _instance;
private CentralServer () {
super();
....
serverName = Configuration.getCentralServerName();
description = Configuration.getCentralServerDescription();
Configuration.initCentralServerPortNumIpMap(portNumIpMap);
Configuration.initCentralServerSubServersList(subServersList);
sizeBlockingQueue = Configuration.initCentralServerBlockingQueueSize();
....
}
public CentralServer getInstance() {
if (_instance == null) {
_instance = new CentralServer();
}
return _instance;
}
....
....
}
The Configuration class, will read and analyze configuration-file, to get out of configuration info.
My Question:
Initialize singleton like this suitable or not, if not, please
give out more suitable approach
I also need configure all sub servers, so seems the Configuration
class is too heavy, should I split the Big Configuration class into
two sub class? class CentralConfiguration, and class
SubConfiguration?
Unfortunately, your implementation for a Singelton is WRONG!! Simply because it is not thread safe.
public CentralServer getInstance() {
if (_instance == null) { // race condition possible here
_instance = new CentralServer();
}
return _instance;
}
Two threads might enter this critical section and evaluate _instance==null to true, and two different instances will be created.
You can simply instantiate your instance statically.
private final static CentralServer INSTANCE = new CentralServer();
public static CentralServer getInstance() {
return INSTANCE;
}
However, the best way to implement singeltons is to use enums
public enum CentralServer { // the best way to implement singletons, due to the author of Effective Java
INSTANCE;
private CentralServer() {
}
}
This gives you serialisation for free.
However, I dont think that you need a singelton at all, singeltons are usually Anti patterns.
Check this out.
In your code, CentralServer has a high dependency on Configuration which I don't think is a good thing, you should see Configuration as a dependency
class CentralServer{
private final Configuration serverConf;
private CentralServer(Configuration serverConf){ // inject configuration
this.serverConf = serverConf;
}
public static CentralServer createCentralServer(Configuration serverConf){ // static factory perhaps
return new CentralServer(serverConf);
}
}
This will give you more flexibility to change or mock configuration. I think Factory pattern would be more appropriate here.
It is perfectly acceptable to make use of external resources during the initialization of your singleton. A common user of the Singleton pattern is loggers and they are almost always configured from external data files.
It does make initialization more complicated but it is not impossible to make a fully tread-safe singleton that accesses external resources such as configuration files. They can even make use of other singletons such as connection pools if their configuration requires database access.
The other answers to this question correctly deal with the actual problems with your singleton initialization.
Initialize singleton like this suitable or not, if not, please give
out more suitable approach:
It is not a suitable approach, because the implementation is not threadsafe yet and it can be broken f.e. via reflection. You should consider reading Effective Java by Joshua Bloch on this topic.
Better would be to create an enum singleton, because this approach is more flexible for later changes, has threadsafe instanciating and is unbreakable.
EDIT: example .
I also need configure all sub servers, so seems the Configuration
class is too heavy, should I split the Big Configuration class into
two sub class? class CentralConfiguration, and class SubConfiguration?
For configuration purposes, there is usually a config.xml file or a config.properties file somewhere to read important preconfigurations. After creating an instance, you should extract the information from such a file and write out necessary changes when shutting down. But as always, many ways lead to rome.