File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Threads and Synchronization and the fly likes No need for synchronization; there is Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "No need for synchronization; there is "Lazy Initialization"" Watch "No need for synchronization; there is "Lazy Initialization"" New topic
Author

No need for synchronization; there is "Lazy Initialization"

Harry Henriques
Ranch Hand

Joined: Jun 17, 2009
Posts: 206
This is from "Effective Java" (p. 283).



Joshua Bloch wrote:When the getField method is invoked for the first time, it reads FieldHolder.field for the first time, causing the FieldHolder class to get initialized. The beauty of this idiom is that the getField method is not synchronized and performs only a field access, so lazy initialization adds practically nothing to the cost of access."


Question: The FieldHolder class is a static nested class, so doesn't the class loader load the nested class when the enclosing class is loaded? If the FieldHolder nested class is loaded when the enclosing class is loaded, then why isn't the static FieldType field initialized with an invocation of computeFieldValue( )? Can't we assume that the computeFieldValue( ) method is also a static method? Is this really "Lazy Initialization"? I don't get it?
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3007
    
    9
Harry Henriques wrote:Question: The FieldHolder class is a static nested class, so doesn't the class loader load the nested class when the enclosing class is loaded?

No. Loading (or rather, initializing) a top-level class does not automatically trigger the loading/initialization of any or all nested types within. Unless there's some other triggering event that occurs during the top-level initialization, like if your top-level class has a static field that needs to be initialized with a reference to an instance of the nested class. A precise description of the rules for this can be found here.

Harry Henriques wrote:If the FieldHolder nested class is loaded when the enclosing class is loaded, then why isn't the static FieldType field initialized with an invocation of computeFieldValue( )? Can't we assume that the computeFieldValue( ) method is also a static method? Is this really "Lazy Initialization"? I don't get it?

The initial assumptions of the question are flawed, so the remaining questions fall apart. Yes, the technique described above by Josh Bloch really is lazy initialization.
Mohammed Yousuff
Ranch Hand

Joined: Oct 17, 2007
Posts: 198
I believe this is the same pattern used in Singleton lazy initialization, rather than a null check... is that correct?


My Thoughts : http://passion4java.blogspot.com
Try not to become a man of success but rather to become a man of value.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3007
    
    9
Yes, that's what the book is discussing on the page Harry gave (p. 283).
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18715
    
  40


To be quite honest, I don't understand the point of this technique. What makes this technique better than just using synchronization, and lazy initialization? Is it to just avoid the synchronized keyword?

So, there isn't a explicit lock being used, but... internal locks are being used (for the class loading), and it is taking an IO hit too, to load the class. How is this better?

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Harry Henriques
Ranch Hand

Joined: Jun 17, 2009
Posts: 206
Thank you for your replies. I have a question that is related to my original question on p. 283 of "Effective Java."

http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.4.1

JLS 12.4.1 wrote: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.




paraphrase wrote:A class T will be initialized immediately before the first occurrence of the following: T is a class and an instance of T is created.


I realize that the "static" nested class FieldHolder is not instantiated in the true sense of instantiation (a "new" operator doesn't invoke its constructor). The "static" nested class FieldHolder can be instantiated using the "new" operator, but the "new" operatior isn't used and the nested class isn't instantiated (in this case) before the getField( ) method accesses the "static" field within the FieldHolder context. What exactly is happening when the getField( ) method accesses the "static" field in the Fieldholder nested class? Is an instance of the FieldHolder nested class created at this time?

Best regards,
Harry Henriques
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4363
    
    8

Henry Wong wrote:
So, there isn't a explicit lock being used, but... internal locks are being used (for the class loading), and it is taking an IO hit too, to load the class. How is this better?

Presumably the point is that this hit is a one-off, whereas using synchronization affects all calls to the static method. Whether that's worth having a less obvious mechanism is a matter of opinion and the particular situation.
Harry Henriques
Ranch Hand

Joined: Jun 17, 2009
Posts: 206
Matthew,

I made a mistake in my previous observation, and edited my last response while you looked at it.

You may want to take another look at my last response after the edit. Now, I think that my question is more accurate.

Best regards,
Harry Henriques
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3007
    
    9
Harry Henriques wrote:What exactly is happening when the getField( ) method accesses the "static" field in the Fieldholder nested class? Is an instance of the FieldHolder nested class created at this time?

No FieldHolder is ever instantiated in this code. However, a static field declared by FieldHolder is used, and the field is not a constant variable. See the 4th item on the list of things that can cause a class to be initialized, which you just quoted.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3007
    
    9
Matthew Brown wrote:
Henry Wong wrote:
So, there isn't a explicit lock being used, but... internal locks are being used (for the class loading), and it is taking an IO hit too, to load the class. How is this better?

Presumably the point is that this hit is a one-off, whereas using synchronization affects all calls to the static method. Whether that's worth having a less obvious mechanism is a matter of opinion and the particular situation.

My guess is that the JVM code to check if it needs to initialize a class is probably optimized pretty well already. That's something they need to do quite routinely, after all, whenever any of those listed events occurs. Much, much more often than synchronization is performed. So however exactly they do it, they've probably put a lot more effort into getting it to happen quickly. My guess is that in terms of performance, it's probably comparable to double-checked locking with a volatile variable. But frankly, it's a lot simpler to code. Or at least shorter - it may be more complex in that it relies on a subtle trick. But hey, if everyone just reads Effective Java, then it will be well-known, and this problem goes away.
Harry Henriques
Ranch Hand

Joined: Jun 17, 2009
Posts: 206
Mike Simmons wrote:No FieldHolder is ever instantiated in this code.


Hi Mike,

I'm not trying to be a wise guy, but how can you initialize the static members of a static nested class that hasn't been instantiated? That's like creating a pearl without the clam.

Curious,
Harry Henriques
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3007
    
    9
Well, since they're static members, you don't need an instance at all to use them, or initialize them. That's pretty much what "static" means when it's used as a modifier for a field or method. Take a look at the java.lang.Math class for example - you can't instantiate it. You just call the static methods, or reference the static fields. No instances needed.
Harry Henriques
Ranch Hand

Joined: Jun 17, 2009
Posts: 206
Mike Simmons wrote:since they're static members, you don't need an instance at all to use them, or initialize them. That's pretty much what "static" means when it's used as a modifier for a field or method.


Hi Mike,

Maybe we are getting somewhere with this line of questioning.

Since they are "static" members of the enclosing class, why isn't FieldHolder ("static" nested class) loaded/initialized when the enclosing class is loaded/initialized/instantiated?

Curious,
Harry Henriques
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3007
    
    9
Wile it might seem to make intuitive sense that initializing a top-level class would trigger the initialization of its member classes, nowhere is this stated in the rules given. It's not one of the five bulleted items above. And the way the rule is phrased, anything not on the list cannot trigger class initialization, because class initialization has to happen immediately before the first event that is on the list. It's not allowed to happen earlier because of some other unlisted event.

Further, look at JLS 12.4:
Initialization of a class consists of executing its static initializers and the initializers for static fields (class variables) declared in the class. Initialization of an interface consists of executing the initializers for fields (constants) declared there.

Nothing about initializing member classes. Just static initializers and static fields.

Or look at the detailed initialization procedure given in JLS 12.4.2. None of those steps says anything about needing to initialize nested classes just because the top-level class is being initialized. Again, we just see static fields and static initializers getting called:
9. Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block, except that final class variables and fields of interfaces whose values are compile-time constants are initialized first (§8.3.2.1, §9.3.1, §13.4.9).

So although it may make intuitive sense for everything within a top-level class to get initialized at the same time, that's not what happens. Nested classes are considered separate classes from the top-level classes that contain them.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: No need for synchronization; there is "Lazy Initialization"