Xiao-Feng,

1. I don't see actually what needs clarification in this statement. :)
If the program needs to invoke a static method of a class, this class'
<clinit> must be invoked by the VM prior to invocation of that static
method.

2. That is simple conclusion from the specificaiton. Look at
initializtion sequence: first class is attempted to be initialized,
then if the class is already is being initialized th sequence checks
if this thread initializes the class and if it is it simply returns.
Our example clearly demonstrates that.

3. Class' static fields are all initialized to zero values on class
preparation. So, any uninitialized fields have the value of 0 (NULL).
Considering (2) we have uninitialized reference to array of Child, so
NPE is produced on invocation of 'return childCache[0];'.

Class initialization is indeed atomic in terms of multithreaded
invocation, but if initialization is requested recursively in the
scope of one thread, all attemps to reenter to <clinit> are aborted. I
do not have the specification at hand but, please, carefully read
through 11-step class initialization procedure to answer your
quesiton.

WBR,
    Pavel.

On Mon, Jan 5, 2009 at 4:04 PM, Xiao-Feng Li <[email protected]> wrote:
> On Mon, Jan 5, 2009 at 7:52 PM, Pavel Pervov <[email protected]> wrote:
>> Xiao-Feng,
>>
>> The spec does not prohibit (and thus just allows) methods (either
>> class or object) to be invoked when circular class initializaiton
>> occurs. The behaviour of such methods is as such that static and
>> object fields are initially initialized to default (zero) values and
>> then assigned other values during class initialization up to the point
>> when circular initialization occurs, and then class or object methods
>> execute without some fields be initialized to "correct" values. It is
>> rather programmatic error or expected program behaviour than some spec
>> inconsistency.
>
>
> Thanks, Pavel.
>
> I have some questions:
>
> 1. How do you explain this statement in VM spec?
> " 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."
>
> 2. As to the semantics you described above, is that defined in any
> spec or that's your understanding?
>
> 3. If to have a NULL value is expected for Child.ROOT in the test
> case, can we simply leave it to be NULL without having: "ROOT =
> Parent.createChild()"?
>
> If the program can not get the expected result with
> Parent.createChild(), I don't understand why we know a NULL is
> expected. :)  I would say it is a program bug because it behaves not
> as the program dictates.
>
> In my understanding, class initialization process is virtually atomic
> semantically. User should not see the intermediate values of a class
> under initialization...
>
> Thanks,
> xiaofeng
>
>> WBR,
>>    Pavel.
>>
>> On Mon, Jan 5, 2009 at 12:06 PM, Xiao-Feng Li <[email protected]> wrote:
>>> Yes, we should commit if it passes the pre-commit tests and it makes
>>> EUT3.5 proceed.
>>>
>>> Btw, we still don't know the expected behavior when a static method is
>>> invoked before its class is initialized. It looks like all the JVMs
>>> just invoke it as usual.
>>>
>>> Thanks,
>>> xiaofeng
>>>
>>> On Mon, Jan 5, 2009 at 4:54 PM, chunrong lai <[email protected]> wrote:
>>>> Thanks.
>>>>
>>>> We still can not make EUT3.5 work. But we have different log/stackTrace 
>>>> this
>>>> time. I will post the new log to HARMONY-6062.
>>>>
>>>> I think the code needs to be committed, if it does not break the precommit
>>>> tests, since it fixes the issue in HARMONY-6020. Opinions?
>>>>
>>>> chunrong
>>>> Managed Runtime Technology Center, Intel
>>>> On Mon, Jan 5, 2009 at 4:48 PM, Xiao-Feng Li <[email protected]> wrote:
>>>>
>>>>> Please try with EUT3.5 before committing... :)
>>>>>
>>>>> Thanks,
>>>>> xiaofeng
>>>>>
>>>>> On Mon, Jan 5, 2009 at 4:34 PM, chunrong lai <[email protected]>
>>>>> wrote:
>>>>> > Thanks for the discussion.
>>>>> > Now it makes sense to me that the initializeClass from newarray 
>>>>> > operation
>>>>> >
>>>>> > //OPCODE_ANEWARRAY
>>>>> > static void *rth_newarray_withresolve(Class_Handle klass, unsigned
>>>>> cp_idx,
>>>>> > unsigned arraySize) {
>>>>> >    ASSERT_THROW_AREA;
>>>>> >    //resolve and init object class
>>>>> >    Class* objClass = resolveClass(klass, cp_idx, false);
>>>>> >    initializeClass(objClass);    //should be removed
>>>>> >    assert(!objClass->is_primitive());
>>>>> >
>>>>> > can be removed.
>>>>> > After removing it I see the HARMONY-6020 and other test cases I built 
>>>>> > can
>>>>> > pass with same behavior with RI. I am going to commit it. For you have
>>>>> more
>>>>> > feedbacks please let me know.
>>>>> >
>>>>> > chunrong
>>>>> > Managed Runtime Technology Center, Intel
>>>>> > On Mon, Jan 5, 2009 at 2:19 PM, Regis <[email protected]> wrote:
>>>>> >
>>>>> >>
>>>>> >>
>>>>> >> Xiao-Feng Li wrote:
>>>>> >>
>>>>> >>> On Mon, Jan 5, 2009 at 5:12 AM, Ian Rogers <[email protected]>
>>>>> >>> wrote:
>>>>> >>>
>>>>> >>>> 2009/1/4 Nathan Beyer <[email protected]>
>>>>> >>>>
>>>>> >>>> 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.
>>>>> >>>
>>>>> >> if add following code to Child
>>>>> >>    static {
>>>>> >>        System.err.println("init Child");
>>>>> >>    }
>>>>> >> the output on RI is:
>>>>> >> null
>>>>> >> init Child
>>>>> >> null
>>>>> >>
>>>>> >> It seems create array of class Child doesn't lead to class Child be
>>>>> >> initialized
>>>>> >>
>>>>> >> if change childCache from array to instance:
>>>>> >>
>>>>> >>    private static final Child childCache = new Child();
>>>>> >>
>>>>> >>    public static Child createChild(){
>>>>> >>        return childCache;
>>>>> >>    }
>>>>> >> the output on RI is:
>>>>> >> init Child
>>>>> >> ch...@affc70
>>>>> >> null
>>>>> >>
>>>>> >> It seems when initialize Child, Parent.createChild() is called, and 
>>>>> >> read
>>>>> >> the value of childCache, it's not initialized, so null is returned 
>>>>> >> (it's
>>>>> >> already in initialize process, so just return null?).
>>>>> >>
>>>>> >>
>>>>> >>> 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.
>>>>> >>>
>>>>> >>> 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
>>>>> >>>>
>>>>> >>>>
>>>>> >>>
>>>>> >>>
>>>>> >>>
>>>>> >> --
>>>>> >> Best Regards,
>>>>> >> Regis.
>>>>> >>
>>>>> >
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>>  Managed Runtime Technology Center, Intel
>>>>>
>>>>
>>>
>>>
>>>
>>> --
>>> Xiao-Feng Li
>>> Managed Runtime Technology Center, Intel
>>>
>>
>
>
>
> --
> Managed Runtime Technology Center, Intel
>

Reply via email to