Discussions

News: Singletons and lazy loading

  1. Singletons and lazy loading (39 messages)

    Dejan Bosanac has posted "Singletons and lazy loading," detailing a trick from Bob Lee (who got it from Jeremy Manson, for whom it sprung whole from the forehead of the Java Memory Model). The trick is the "Initialization on Demand Holder (IODH) idiom," and it manages to correctly instantiate a singleton on demand without sync problems. In short, here's the correct way to lazily-load singletons from the post:
    public class Singleton { static class SingletonHolder { static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }Basically, Java Language Specification (JLS) guarantees that instance would not be initialized until someone calls getInstance() method (more information could be found in articles that I’ve linked to before). Elegant and fast, just as it should be.

    Threaded Messages (39)

  2. I have two questions: 1. Is this also correct in Java 1.4, or is it correct only since Java 5 or Java 6? 2. Is there a difference if the SingletonHolder class and/or the instance static member is made private? BR, Robert
  3. I have two questions:

    1. Is this also correct in Java 1.4, or is it correct only since Java 5 or Java 6?
    Actually in 1.5+ you can (according to reputable sources) implement double-checked locking using volatile. Of course the use of volatile adds overhead but not much. Actually the overhead of synchronized isn't much either.
    2. Is there a difference if the SingletonHolder class and/or the instance static member is made private?

    BR,

    Robert
    No and you should definitely make the inner class private if you use this idiom.
  4. Re: Singletons and lazy loading[ Go to top ]

    This pattern has been discussed on TSS before: http://www.theserverside.com/patterns/thread.tss?thread_id=17614#80587
  5. also was discussed[ Go to top ]

    This also has been discussed in Effective Java Programming Language Guide by Joshua Bloch.
  6. Re: Singletons and lazy loading[ Go to top ]

    Basically, Java Language Specification (JLS) guarantees that instance would not be initialized until someone calls getInstance() method
    I'm not convinced this is true. If I change the code to this: public class Singleton { private static class SingletonHolder { static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } private Singleton() { System.out.println("loaded"); } } And create a test class like so: class Test { public static void main(String[] args) throws Exception { Class.forName("Singleton$SingletonHolder"); } } This prints "loaded" when I run the Test class. Now that either means that the 1.6 compiler and or JVM is broken or this claim is not true. Of course, why this would occur is another question but it's clearly possible to load the Singleton before the getInstance() method is called.
  7. Re: Singletons and lazy loading[ Go to top ]


    Now that either means that the 1.6 compiler and or JVM is broken or this claim is not true. Of course, why this would occur is another question but it's clearly possible to load the Singleton before the getInstance() method is called.
    Actually, the statement is poorly worded. Whether or not getInstance() is called, the instance variable will not be initialized until the SingletonHolder class is loaded. And under normal circumstances, it won't be loaded until getInstance() is called...although you've shown one way that it might be loaded without calling getInstance(). This idiom takes advantage of the fact that there's no way to use SingletonHolder until it has been loaded and there's no way to load it without initializing the static instance variable. This removes the opportunity for a competing thread to tinker with the instance variable before it is fully initialized. In any event, whether instance is initialized before getInstance() is called or when getInstance() uses SingletonHolder, it will certainly have the singleton instance ready by the time that getInstance() returns. (All without synchronization or a null check.)
  8. Re: Singletons and lazy loading[ Go to top ]

    This removes the opportunity for a competing thread to tinker with the instance variable before it is fully initialized.
    Yes but you get this with just a normal non-nested static reference. The whole point of the on-demand holder idiom is that it's lazy-loaded. The point of my example is that people assume it's equivalent to the 'standard' lazy-loaded solution. It is, under most circumstances, yes. But I don't think it's proper present something as an expert tip like 'the JLS ensures W' when in fact it does not ensure X.
  9. Re: Singletons and lazy loading[ Go to top ]

    tip like 'the JLS ensures W' when in fact it does not ensure X.
    My keyboard is clearly malfunctioning. I meant 'the JLS ensures X' if that was not clear.
  10. Re: Singletons and lazy loading[ Go to top ]

    James:
    Class.forName("Singleton$SingletonHolder");
    James, Class.forName(String) forces the static initializer to run. That's why your example printed "loaded." If you don't want it to run, use Class.forName(String, boolean, ClassLoader) instead. Brad:
    So, seriously... what is the point of lazy loading singletons? Do you have THAT many singletons? Is there something offensive about loading something in advance of needing it? To me this pattern is a solution looking for a problem, and I haven't yet found that problem -- maybe somebody can enlighten me as to how this is useful?
    Brad, eagerly loading everything every time you start your server during development is a waste of time.
  11. Re: Singletons and lazy loading[ Go to top ]

    James:
    Class.forName("Singleton$SingletonHolder");


    James, Class.forName(String) forces the static initializer to run. That's why your example printed "loaded." If you don't want it to run, use Class.forName(String, boolean, ClassLoader) instead.
    What I wanted was to demonstrate that the statement 'the JLS guarantees that the singleton won't be loaded until getInstance() is called' is patently false. So the version I called was exactly correct.
  12. Re: Singletons and lazy loading[ Go to top ]

    Bob:
    Brad, eagerly loading everything every time you start your server during development is a waste of time.
    This makes it sound like you use nothing but singletons! It's not a bad thing to load up during bootstrap to do as few expensive things as possible during runtime. Your point is taken, though, that it depends on the desired characteristics of your program, but that sorta goes back to my original argument that I've never been in the situation that I wanted this. Robert Varga's reply has helped me fill in that gap a bit (although I remain steadfastly dubious *grin*). Oh, and I waste my CPU's time constantly, I'm not too worried about it *broad grin* (this is meant as humor, not trolling)
  13. Re: Singletons and lazy loading[ Go to top ]

    Bob:

    Brad, eagerly loading everything every time you start your server during development is a waste of time.


    This makes it sound like you use nothing but singletons! It's not a bad thing to load up during bootstrap to do as few expensive things as possible during runtime. Your point is taken, though, that it depends on the desired characteristics of your program, but that sorta goes back to my original argument that I've never been in the situation that I wanted this.
    I actually had a problem long ago where we had to use lazy-loading to make the code behave properly. The class would get loaded before it's resources were available and be defunct making all the code that used the Singleton fail. Some sort of aggresive classloader issue. Never could put a finger on the problem. Probably a bug the app server (yes I know you're not supposed to create singletons in app-server deployed apps.)
  14. The Class.forName(...) will load the singleton of course, but it's also thread-safe if happens concurrently with other threads that trigger that loading (either with other Class.forName() calls, or with the standard call to the singleton's getter). That's the point. Now, I wouldn't expect the holder class to be subject to reflection, ever... this looks just like a strawman, an artificial problem to dismiss the technique. The holder class exists SOLELY do do that initialization. You should never expect this class to be loaded through reflection. If you ever have needs like dependency injection or Java5 annotations, put that stuff in the main singleton and not in the holder.
  15. The Class.forName(...) will load the singleton of course, but it's also thread-safe if happens concurrently with other threads that trigger that loading (either with other Class.forName() calls, or with the standard call to the singleton's getter). That's the point.
    It doesn't guarantee the same operation order as lazy-loading. That's the point. A lot of people seem confused about this. If all you care about avoiding synchronization and you don't care about lazy-loading, you don't need this idiom. Just assign the instance to a static final reference in the Singleton class.
    Now, I wouldn't expect the holder class to be subject to reflection, ever...
    Your expectations and what the JLS guarantees are clearly very different things. I don't think the blog made any mention about your expectations.
    this looks just like a strawman, an artificial problem to dismiss the technique.
    Wrong. It's a demonstration that the JLS does not guarantee lazy-loading. The technique will probably work for most intents and purposes requiring lazy-loading.
    The holder class exists SOLELY do do that initialization. You should never expect this class to be loaded through reflection. If you ever have needs like dependency injection or Java5 annotations, put that stuff in the main singleton and not in the holder.
    you can't eliminate the possibility of an aggressive classloader or application server that would initialize these classes ahead of time and in an indeterminate order. I work with a JRE that actually pre-compiles classes to machine instructions before the application is run in part to minimize the startup time. Would this work in that environment? I'm not sure, given that the JVM can demonstrably load the singleton instance before getInstance() is called.
  16. Re: Singletons and lazy loading[ Go to top ]

    Wrong. It's a demonstration that the JLS does not guarantee lazy-loading.
    Actually, you're incorrect, James. In my original blog post, I even linked to section 12.4.1 of the JLS ("When Initialization Occurs") which spells out exactly when initialization occurs and guarantees lazy initialization (emphasis mine):
    A class or interface type T will be initialized immediately before the first occurrence of any one of the following: * T is a class and an instance of T is created. * T is a class and a static method declared by T is invoked. * A static field declared by T is assigned. * A static field declared by T is used and the field is not a constant variable (§4.12.4). * T is a top-level class, and an assert statement (§14.10) lexically nested within T is executed. Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization. A class or interface will not be initialized under any other circumstance.
  17. Re: Singletons and lazy loading[ Go to top ]

    Wrong. It's a demonstration that the JLS does not guarantee lazy-loading.


    Actually, you're incorrect, James. In my original blog post, I even linked to section 12.4.1 of the JLS ("When Initialization Occurs") which spells out exactly when initialization occurs and guarantees lazy initialization
    So how does the code example show produce the output that it does? Are you saying the JVM or compiler is broken or something else? Like I said above, one of two things must be true, Sun's 1.6 compiler or JVM is not correct per the JLS or the JLS doesn't guarantee these things. It's great to point to a document and all but it doesn't really change what's actually happening.
  18. Re: Singletons and lazy loading[ Go to top ]

    So how does the code example show produce the output that it does?
    I already explained that calling Class.forName() forces class initialization. From the Javadocs:
    A call to forName("X") causes the class named X to be initialized.
    And the JLS allows for this:
    Invocation of certain reflective methods in class Class ... also causes class or interface initialization.
  19. Re: Singletons and lazy loading[ Go to top ]

    So how does the code example show produce the output that it does?

    I already explained that calling Class.forName() forces class initialization. From the Javadocs:

    A call to forName("X") causes the class named X to be initialized.


    And the JLS allows for this:

    Invocation of certain reflective methods in class Class ... also causes class or interface initialization.
    OK I was clear on all that. What I don't understand is you can say that lazy-loading is guaranteed by the JLS given the above.
  20. Re: Singletons and lazy loading[ Go to top ]

    ...which spells out exactly when initialization occurs and guarantees lazy initialization (emphasis mine):
    ...Invocation of certain reflective methods in class Class and in package java.lang.reflect also causes class or interface initialization...
    Actually, you quoted the exact text that points out why lazy initialization is not guaranteed. I knew it was somewhere around there but I kept missing it. I'm confused as to what you are arguing here. Are you saying that is guarantees lazy-loading? I think the code I posted demonstrates that is does not unless you are saying there's a problem with the compiler or JVM (which the above suggests is not the case.)
  21. Re: Singletons and lazy loading[ Go to top ]

    People are still coding singletons?
  22. Re: Singletons and lazy loading[ Go to top ]

    Indeed. A singleton in what context? Lets not forget class loading and its wonders and pain. Colin. http://hermesjms.com
  23. Re: Singletons and lazy loading[ Go to top ]

    Indeed. A singleton in what context?
    That's a very appropriate question. Some may say "I'm using Spring, where everything's a singleton by default, so I don't need singletons anymore." That's probably true in a lot of cases, but it's important to realize that in Spring, "singleton" refers to a bean definition within the Spring container. It only guarantees that that particular configuration of a class won't be instantiated by Spring more than once. It does not promise that a different configuration of the same class won't be created or that the programmer cannot instantiate the class themselves in code. The Gang of Four style of Singleton is meant to ensure only one instance within the context of the application. Spring can't do that, so if you need a true singleton (for whatever reasons you may have), you'll still want to develop it in a non-Spring way (and then inject them into Spring using the factory-method attribute). But even then, if you want to nitpick, the GoF singleton isn't a singleton in the truest sense of the word. A true singleton would be universally unique, with only one instance shared among all applications...everywhere. Of course, such a singleton would be difficult to write and would have very limited usefulness, so there's little point in discussing it further. Which brings me back to the GoF Singleton, which I think can (and has been) used when it really isn't necessary. I try to avoid writing GoF singletons, but stop short of calling them evil and will write one when the circumstances won't settle for an alternate approach.
  24. Re: Singletons and lazy loading[ Go to top ]

    The Gang of Four style of Singleton is meant to ensure only one instance within the context of the application. Spring can't do that, so if you need a true singleton (for whatever reasons you may have), you'll still want to develop it in a non-Spring way (and then inject them into Spring using the factory-method attribute).
    I think the point was that because classes can be loaded multiple times in different classloaders, it's fairly difficult to do this in Java at all. In an application server, for example, there are many times where the class must be loaded more than once to be used in two sibling classloaders. The biggest problem I have with this whole thing about Singletons is that while you might want to have a logical 'singleton' it shouldn't be important that there is literally only one instance of the class, at least to the clients of that class. I might use a Singleton like class every once in a while (usually as a stop-gap meant to be changed) but I never make it's Singleton-ness part of it's contract.
  25. Re: Singletons and lazy loading[ Go to top ]

    James: I think we're on the same page here. My point was that the term "singleton" is relative to a context. You pointed out, multiple classloaders make it really hard to ensure the singleton-ness of a class. That point wasn't lost on me...I just didn't want to rehash it. Instead, I used Spring singletons and the idealogical universal singleton as two examples of how singleton-ness is a relative concept. To sum up my thoughts, it's really hard to ensure that a class is a singleton. It may be a singleton in one context, but not in another. Therefore, as you said quite well, a class may be a singleton, but its singleton-ness shouldn't define its contract.
    The Gang of Four style of Singleton is meant to ensure only one instance within the context of the application. Spring can't do that, so if you need a true singleton (for whatever reasons you may have), you'll still want to develop it in a non-Spring way (and then inject them into Spring using the factory-method attribute).


    I think the point was that because classes can be loaded multiple times in different classloaders, it's fairly difficult to do this in Java at all. In an application server, for example, there are many times where the class must be loaded more than once to be used in two sibling classloaders.

    The biggest problem I have with this whole thing about Singletons is that while you might want to have a logical 'singleton' it shouldn't be important that there is literally only one instance of the class, at least to the clients of that class. I might use a Singleton like class every once in a while (usually as a stop-gap meant to be changed) but I never make it's Singleton-ness part of it's contract.
  26. Re: Singletons and lazy loading[ Go to top ]

    Indeed. A singleton in what context?


    That's a very appropriate question.

    Some may say "I'm using Spring, where everything's a singleton by default, so I don't need singletons anymore." That's probably true in a lot of cases, but it's important to realize that in Spring, "singleton" refers to a bean definition within the Spring container. It only guarantees that that particular configuration of a class won't be instantiated by Spring more than once. It does not promise that a different configuration of the same class won't be created or that the programmer cannot instantiate the class themselves in code.

    The Gang of Four style of Singleton is meant to ensure only one instance within the context of the application. Spring can't do that, so if you need a true singleton (for whatever reasons you may have), you'll still want to develop it in a non-Spring way (and then inject them into Spring using the factory-method attribute).

    But even then, if you want to nitpick, the GoF singleton isn't a singleton in the truest sense of the word. A true singleton would be universally unique, with only one instance shared among all applications...everywhere. Of course, such a singleton would be difficult to write and would have very limited usefulness, so there's little point in discussing it further.

    Which brings me back to the GoF Singleton, which I think can (and has been) used when it really isn't necessary. I try to avoid writing GoF singletons, but stop short of calling them evil and will write one when the circumstances won't settle for an alternate approach.
    Actually, it's true that in a Spring-based app you'd probably never really need the Gang of Four style of Singleton (one instance for the whole classloader). You generally get more control by using a singleton Spring bean, which you can easily dependency inject, still have multiple instance of that class as multiple beans, and so on... But if you did need, you could actually do it pretty easily by implementing a custom scope. I doubt we'll ever see this, there aren't a lot of use case... Colin
  27. Whew, what a relief[ Go to top ]

    I'm glad that somebody finally solved this problem because it's been keeping me up at night. So, seriously... what is the point of lazy loading singletons? Do you have THAT many singletons? Is there something offensive about loading something in advance of needing it? To me this pattern is a solution looking for a problem, and I haven't yet found that problem -- maybe somebody can enlighten me as to how this is useful?
  28. Re: Whew, what a relief[ Go to top ]

    I'm glad that somebody finally solved this problem because it's been keeping me up at night.
    I really like the solution, and it probably did keep me up a few nights wondering ;-) Peace, Cameron Purdy Tangosol Coherence: The Java Data Grid
  29. Re: Whew, what a relief[ Go to top ]

    Cameron:
    I really like the solution, and it probably did keep me up a few nights wondering ;-)
    Oof, now I feel bad for the original tone of my post. Maybe I'll have pick up a copy of Java Puzzlers to make up for it :-) Thanks for the perspective.
  30. Re: Whew, what a relief[ Go to top ]

    I'm glad that somebody finally solved this problem because it's been keeping me up at night.

    So, seriously... what is the point of lazy loading singletons? Do you have THAT many singletons? Is there something offensive about loading something in advance of needing it? To me this pattern is a solution looking for a problem, and I haven't yet found that problem -- maybe somebody can enlighten me as to how this is useful?
    Actually this problem (lazy initialized singletons) does have a right of existence. Just imagine a situation, where you CAN't ensure that the class holding the singleton instance is loaded AFTER all resources to initialize the singleton instance are available. In this situation you might not be able to successfully initialize the singleton at class-loading time, therefore you would need to do it on-demand.
  31. Re: Whew, what a relief[ Go to top ]

    ... you CAN't ensure that the class holding the singleton instance is loaded AFTER all resources to initialize the singleton instance are available.
    Sorry, this wanted to be: ... you CAN'T ensure that the class defining the >>> getInstance() method <<< is loaded AFTER all resources to initialize the singleton instance are available.
  32. Effective java says - // The initialize-on-demand holder class idiom private static class FooHolder { static final Foo foo = new Foo(); } public static Foo getFoo() { return FooHolder.foo; } JLS ensure lazy loading...
  33. Re: Singletons and lazy loading[ Go to top ]

    There is one problem with this approach that did not get mentioned here: you only get one attempt at instantiating the singleton this way. If SingletonHolder static initializer throws an exception, the classloader will not attempt to load the inner class again on subsequent calls to getInstance():
    public class Singleton { static class SingletonHolder { static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } public Singleton() { throw new RuntimeException("Try again"); } } ... public void test() { try { Singleton.getInstance(); } catch (Throwable t) { System.out.println("First attempt: " + t); } try { Singleton.getInstance(); } catch (Throwable t) { System.out.println("Second attempt: " + t); } }
    The test() method outputs: First attempt: java.lang.ExceptionInInitializerError Second attempt: java.lang.NoClassDefFoundError I can't think of a way around this. If exception is handled in the static initializer, then on subsequent getInstance() calls we have the old synchronization problem. Leon
  34. Re: Singletons and lazy loading[ Go to top ]

    There is one problem with this approach that did not get mentioned here: you only get one attempt at instantiating the singleton this way.
    static class SingletonHolder { static Singleton instance; static { try { instance = new Singleton(); } catch (Throwable t) { // Try again. instance = new Singleton(); } } } public static Singleton getInstance() { return SingletonHolder.instance; }
  35. Re: Singletons and lazy loading[ Go to top ]

    Bob, This still counts as one attempt from client's standpoint. What if the singleton is trying to acquire some external resource and I don't want clients to block until it becomes available, but rather deal with an exception? The synchronized version of lazy initialization does not have this limitation. This limitation may not be important in some contexts, but it's common to go for lazy singleton initialization when it requires some havy/lengthy processing involving external resources. Leon
  36. Re: Singletons and lazy loading[ Go to top ]

    Bob,

    This still counts as one attempt from client's standpoint.

    What if the singleton is trying to acquire some external resource and I don't want clients to block until it becomes available, but rather deal with an exception?

    The synchronized version of lazy initialization does not have this limitation.

    This limitation may not be important in some contexts, but it's common to go for lazy singleton initialization when it requires some havy/lengthy processing involving external resources.

    Leon
    Yes, if you want to change the reference after the class has loaded (you're talking about changing it from null to non-null), you'll have to use synchronization or DCL.
  37. Re: Singletons and lazy loading[ Go to top ]

    This still counts as one attempt from client's standpoint.

    What if the singleton is trying to acquire some external resource and I don't want clients to block until it becomes available, but rather deal with an exception?

    The synchronized version of lazy initialization does not have this limitation.

    This limitation may not be important in some contexts, but it's common to go for lazy singleton initialization when it requires some havy/lengthy processing involving external resources.
    Along with this case, the holder idiom also does not allow for the singleton to be invalidated and restored later. This can be a problem in long running programs like web-apps where you might lose a resource temporarily and then regain it later (perhaps shortly thereafter.) With the holder idiom you need to reload the class which almost invariably means restarting the application.
  38. Re: Singletons and lazy loading[ Go to top ]

    How bizarre. Why would that be more "elegant" than the "synchronized" block? Even if it might be faster then the synchronzed block, I wonder if it would ever be worth the effort to remember, why this works :-).
  39. not so easy...[ Go to top ]

    the solution is far from easy to understand for the beginners, it would require extensive comments to avoid other people in the team to break it. All in all much better to stick at using boolean flags for double checking (which, according to te original article, are safe)!
  40. Re: not so easy...[ Go to top ]

    the solution is far from easy to understand for the beginners, it would require extensive comments to avoid other people in the team to break it.
    It's not difficult to understand. Class initialization is always effectively synchronized in Java. Nothing can refer to any of the class members until it has completed initialization.
    All in all much better to stick at using boolean flags for double checking (which, according to te original article, are safe)!
    Where does it say that this is safe? It's double-checked locking is definitely not safe in pre 1.5 and in 1.5 and above you must use volatile to make it safe.