> This prints:
If I call Foo.getDefaultCacheStrategy() from another class, of course :)
> This prints:
> 2 getDefaultCacheStrategy() null
> 1 static{} myvalue
Unless I'm mis-reading your code, it /shouldn't/ do that. The static
initialisation should have completed before the static method is entered.
Possibly there's something wrong with your real code that doesn't appear in the
snippet you posted; can you create a complete self-contained example ?
-- chris
John C. Bollinger - 14 Jun 2005 14:56 GMT
>>This prints:
>>2 getDefaultCacheStrategy() null
[quoted text clipped - 4 lines]
> Possibly there's something wrong with your real code that doesn't appear in the
> snippet you posted; can you create a complete self-contained example ?
I agree that the posted code does not explain the observed behavior, but
I have a guess as to how it's happening. Class initializers -- the
combination of static variable initialization expressions and static
initializer blocks -- are executed at runtime in the order they appear
in the class' code. My bet would be that the getDefaultCacheStrategy()
method is invoked within the scope of some method call in one of the
initializers preceding the static initializer block shown. Because the
class is at that point already in the process of initialization, the
method call proceeds without attempting to start a new initialization,
and the unexpected execution order and default value of
defaultCacheStrategy are observed. This would be akin to a superclass
constructor invoking a virtual method, and thereby exposing a subclass'
instance variable before it has been initialized by the subclass
constructor.
Schematic sequence:
() class Foo is uninitialized at the beginning of the sequence
() Foo.getDefaultCacheStrategy() is invoked
() the VM loads class Foo, and begins initializing it
() static member baz is initialized by invoking (hypothetical) static
method Foo.getCache()
() Foo.getCache() invokes Foo.getDefaultCacheStrategy(), which prints
the observed message containing the default value for the
defaultCacheStrategy variable
() static member defaultCacheStrategy is initialized via its initializer
() the VM runs the static initializer block, which prints the second
message (numbered 1) which includes the initialized value of
defaultCacheStrategy
() initialization of Foo is complete, execution of
Foo.getDefaultCacheStrategy() begins (for the second time)
() Another message numbered 2 is printed (not reported by the OP)
That's the only thing I can think of. A class method cannot ever be
invoked before its class is initialized, but it can be invoked *while*
its class is being initialized, in which case it will see a partially
initialized class.

Signature
John Bollinger
jobollin@indiana.edu
Timo Nentwig - 14 Jun 2005 18:25 GMT
>> This prints:
>> 2 getDefaultCacheStrategy() null
>> 1 static{} myvalue
>
> Unless I'm mis-reading your code, it /shouldn't/ do that. The static
Yes, I found the bug today:
class Foo
{
// the bug:
private static final DEFAULT_INSTANCE = new Foo();
private static final ConditionalPropertiesReader PROPERTIES =
ConditionalPropertiesReader.getInstance();
private static final String defaultCacheStrategy =
PROPERTIES.getProperty( "jcms.cache.strategy" );
...
// I have to put the singleton stuff here
// as it depends on the lines above
}
Chris Uppal - 15 Jun 2005 09:06 GMT
> class Foo
> {
> // the bug:
> private static final DEFAULT_INSTANCE = new Foo();
Aha!
That's really quite a cute little bug ;-)
-- chris
Timo Nentwig - 15 Jun 2005 19:23 GMT
> That's really quite a cute little bug ;-)
Isn't it? :) I must admit I'm somewhat proud of it indeed ;)