Re: Puzzling class field initialization order

Attila Szegedi <[email protected]>
Newsgroups gmane.comp.windows.devel.java.advanced
Message-ID <[email protected]>
On Thu, 06 Sep 2007 16:07:35 +0200, Brian Maso <[email protected]>  
wrote:

>
> So based on that, it seems the 1.5.0 VM you are using is not breaking  
> the initialization ordering rules -- although it certainly is surprising  
> that the interface initialization is delayed. It's a pretty wild case  
> though with the superclass and superinterface static field actually  
> dependant on the subclass/implementing class static fields. How did you  
> even think to come up with it?

Distilling a real-world example, of course :-)

Namely, FreeMarker has an interface named "ObjectWrapper", which has a  
static final field named BEANS_WRAPPER that's initialized to static final  
BeansWrapper.DEFAULT_INSTANCE, which in turn is initialized to "new  
BeansWrapper()". And BeansWrapper implements ObjectWrapper. It's actually  
something that FindBugs pinpointed as a potential problem, so I decided to  
poke around. Actually, we'll probably end up removing the whole bunch of  
those static fields for unrelated reasons (namely, because of the  
Singletons Are Evil rule).

Attila.

>
> Brian Maso
>
> At 06:22 AM 9/6/2007, you wrote:
>> Hi folks,
>>
>> I observed an interesting behaviour in initialization of static fields,
>> and am unable to understand it. Can anyone help? Here's the code  
>> distilled
>> to absolute minimum demonstrating the problem, in four classes:
>>
>> S.java:
>> =======
>> class S {
>>     static final C IMPL = C.INSTANCE;
>> }
>>
>> I.java:
>> =======
>> interface I {
>>     static final C IMPL = C.INSTANCE;
>> }
>>
>> C.java:
>> =======
>> class C extends S implements I {
>>     static final C INSTANCE = new C();
>> }
>>
>> X.java:
>> =======
>> public class X {
>>     public static void main(String[] args) {
>>         C c = new C();
>>         System.out.println(S.IMPL);
>>         System.out.println(I.IMPL);
>>     }
>> }
>>
>> Running X prints null for S.IMPL, as expected, since S.IMPL was
>> initialized before C.INSTANCE when C was loaded. That's perfectly
>> understandable.
>>
>> *However* it prints a non-null instance for I.IMPL, i.e. "C@2e7263"!  
>> Now,
>> anyone care to explain why isn't I.IMPL null as well? It is likely
>> something related to a difference in loading a superclass vs. loading a
>> superinterface, but if anyone has a definitive explanation (a pointer to
>> the relevant JVM spec section will suffice :-)), I'd appreciate that.
>>
>> BTW, Java runtime version is:
>>
>> java version "1.5.0_07"
>> Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-164)
>> Java HotSpot(TM) Client VM (build 1.5.0_07-87, mixed mode, sharing)
>>
>> Thanks,
>>   Attila.

===================================
This list is hosted by DevelopMentor®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.