Static blocks don't run when class loaded under jdk 1.5

I'm seeing a new behavior regarding when static code blocks run in jdk 1.5.

In earlier VM's, the static block in the following code would execute as soon as I called MyClass.class.getName().

I never had to actually call a method on the class.

MyClass class {

static String myStaticString;

// static code block

static {

myStaticString = "hello";

}

static init() { //do nothing }

}

Under JDK 1.5, I would now have to call MyClass.init() in order to get the static block to run. This is very troublesome for the many Abstract Factory/Singleton classes I use that are dynamically instantiated at runtime. Is this a bug, or is there an recommended workaround?

Thanks,

Dan

[758 byte] By [bhamail] at [2007-9-30 18:25:04]
# 1
Seems like MyClass.class.getName() gets optimized - no need to load the class to figure out its name.The canonical way to force class loading, Class.forName(), works as expected.
sjasja at 2007-7-6 19:35:32 > top of Java-index,Administration Tools,Sun Connection...
# 2

> Is this a bug, or is there an recommended

> workaround?

Did you check the bug database?

There isn't anything explicit in your code that suggests to me that it must be a bug.

From the JVM spec for 12.4.1....

http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html#57946

Initialization of a class consists of executing its static initializers and the initializers for static fields declared in the class. Initialization of an interface consists of executing the initializers for fields declared in the interface.

Before a class is initialized, its direct superclass must be initialized, but interfaces implemented by the class need not be initialized. Similarly, the superinterfaces of an interface need not be initialized before the interface is initialized.

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 reference to the field is not a compile-time constant (?5.28). References to compile-time constants must be resolved at compile time to a copy of the compile-time constant value, so uses of such a field never cause initialization.

...

Given that 'class' is defined as literal and not as any of the above, it is possible that the previous VMs are the ones with the bug.

However the class literal is not mentioned in the compile time constants either (although that could be a documentation bug.)

jschell at 2007-7-6 19:35:32 > top of Java-index,Administration Tools,Sun Connection...
# 3

I've just come across the same problem whilst using the jakarta commons Enum class under JDK1.5; previously it was sufficient just to reference the class literal in code in order for the class to be loaded, now that no longer applies.

Using class.forName does workaround the problem, but in order to continue using the class literal the following (ugly) code now needs to be used:

Class.forName(MyClass.class.getName())

where previously

MyClass.class

would have been sufficient.

Regardless of what the spec. may or may not say, this is a fairly subtle change that could have huge implications for some developers' code.

jimnick at 2007-7-6 19:35:32 > top of Java-index,Administration Tools,Sun Connection...
# 4

>

> Regardless of what the spec. may or may not say, this

> is a fairly subtle change that could have huge

> implications for some developers' code.

>

Yes. But so was the enforcement of importing classses in the default name space when 1.3 came out.

jschell at 2007-7-6 19:35:32 > top of Java-index,Administration Tools,Sun Connection...