mysterious static

T

Timo Nentwig

Hi!

I'm somewhat confused:

class Foo
{
private static final ConditionalPropertiesReader PROPERTIES =
ConditionalPropertiesReader.getInstance();
private static final String defaultCacheStrategy =
PROPERTIES.getProperty( "jcms.cache.strategy" );

static
{
System.out.println("1 static{}"+defaultCacheStrategy);
}
....
public static IJCMSCacheStrategy getDefaultCacheStrategy()
{
System.out.println("2 getDefaultCacheStrategy()
"+defaultCacheStrategy);

return JCMSCacheStrategy.Factory.make( defaultCacheStrategy != null
? defaultCacheStrategy
:
JCMSCacheStrategy.Factory.CACHESTRATEGY_DEFAULT );
}
}


This prints:
2 getDefaultCacheStrategy() null
1 static{} myvalue


Why is that?? If I create an instance of the class prior to calling the
method defaultCacheStrategy in getDefaultCacheStrategy() *does* have the
supposed value. And why is 2 printed first??

Can somebody explain?
 
C

Chris Uppal

Timo said:
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
 
J

John C. Bollinger

Chris said:
Timo Nentwig wrote:




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 ?

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.
 
T

Timo Nentwig

Chris said:
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
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top