harmony-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Xiao-Feng Li" <xiaofeng...@gmail.com>
Subject Re: [class loading] what's the expected behavior when a static method is invoked before its class is initialized?
Date Mon, 05 Jan 2009 06:44:38 GMT
On Mon, Jan 5, 2009 at 1:10 PM, Nathan Beyer <ndbeyer@apache.org> wrote:
> On Sun, Jan 4, 2009 at 10:08 PM, Xiao-Feng Li <xiaofeng.li@gmail.com> wrote:
>> On Mon, Jan 5, 2009 at 5:12 AM, Ian Rogers <rogers.email@gmail.com> wrote:
>>> 2009/1/4 Nathan Beyer <ndbeyer@apache.org>
>>>> Could any of the IBM folks on the list get some advice from some class
>>>> loader experts?
>>>> -Nathan
>>>  Hi Nathan,
>>> from reading the description I can describe how Jikes RVM avoids this
>>> problem (I'm not an IBM VME expert and I've not run the test case to check
>>> that Jikes RVM passes it). In Jikes RVM we have two variants of all calls,
>>> ones to unresolved methods and ones to resolved methods. Unresolved calls
>>> are to classes whose initializer hasn't yet been run. If two threads are
>>> calling a static method the first will resolve it and in the process acquire
>>> a lock, the second thread must wait for the lock before it can attempt to
>>> resolve the method (at which point it will discover the method was resolved
>>> by the other thread and leave early). Checking for classes being resolved
>>> litters all of the class loader code, and we're slightly proactive in
>>> resolving in the case of reflected methods so that we needn't check for
>>> resolution when performing reflected method invocation (which is now pretty
>>> much unnecessary since [1] where we generate bytecodes at runtime to perform
>>> reflection). An aside, I wrote a paper where I use the class loader as a
>>> test case for optimizations based on stationary/immutable fields specified
>>> via constraints [2], this work specialized the class loader to handle the
>>> resolved case as a class is normally accessed when it is resolved (figures
>>> in the paper).
>> Thanks for the explanation.
>> Let me try to explain the problem we are meeting:
>> 1. A thread invokes a static method createChild of a class Parent. It
>> causes class Parent be initialized.
>> 2. In Parent's initialization, it creates an array of class Child. It
>> leads to class Child be initialized.
> Is this the problem? The initialization bit in the spec only says that
> a non-constant field [1] that references a type T, should cause the
> initialization of type T. This brings up two questions for me. One,
> does that implicitly include arrays of a type T? Two, why is Child
> getting loaded in the example, since it is a constant (static and
> final)?

For your questions:
1. It has two operations: a) to create an array of Child, and b) to
assign it to an array reference. Both a) and b) might not require the
class initialization. It can be verified by using:

   private static final Object childCache = new Child[5];

2. This is not a constant, because it is not compile-time value.

> The second bit seems to be violating the spec. Am I reading it wrong?
> [1] http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html#19075
>> 3. In Child's initialization, it invokes Parent.createChild() to
>> initialize a static field ROOT. This leads to re-entrance of Parent
>> initialization.
>> 4. The thread finds Parent is under initialization by itself, it quits
>> the initialization process and invokes Parent.createChild().
>> 5. This invocation should not be permitted by the VM spec, and we
>> don't know how to deal with it. It can't wait for the initialization
>> process finished, because it is in the path of the initialization. It
>> has to do something to proceed with the initialization.
> Since you put "should not" in this statement, I presume this is just
> an opinion and their isn't any source that supports this, correct?

As the spec says:

A class or interface type T will be initialized immediately before one
of the following occurs:
    * T is a class and a static method of T is invoked.


> -Nathan
>> Below is the code of the micro test. Chunrong, please correct me if my
>> understanding is inaccurate.
>> So my suggestion is to ignore the static method invocation for the
>> class under initialization...
>> public class Main {
>>    public static void main(String[] args) {
>>        Child c = Parent.createChild();
>>        System.err.println(c);
>>        System.err.println(Child.ROOT);
>>    }
>> }
>> class Parent {
>>    private static final Child[] childCache = new Child[5];
>>    public static Child createChild(){
>>        return childCache[0];
>>    }
>> }
>> class Child {
>>    public static final Child ROOT = Parent.createChild();
>> }
>> Thanks,
>> xiaofeng
>>> Regards,
>>> Ian Rogers
>>> [1]
>>> http://icooolps.loria.fr/icooolps2008/Papers/ICOOOLPS2008_paper08_Rogers_Zhao_Watson_final.pdf
>>> [2] http://portal.acm.org/citation.cfm?id=1411746
>> --
>> Managed Runtime Technology Center, Intel

Xiao-Feng Li
Managed Runtime Technology Center, Intel

View raw message