harmony-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "chunrong lai" <chunrong...@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 08:34:59 GMT
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 <xu.regis@gmail.com> wrote:

>
>
> Xiao-Feng Li 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.
>>
> 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
> Child@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.
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message