harmony-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Pavel Pervov" <pmcfi...@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 11:52:48 GMT
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.

WBR,
    Pavel.

On Mon, Jan 5, 2009 at 12:06 PM, Xiao-Feng Li <xiaofeng.li@gmail.com> 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 <chunronglai@gmail.com> 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 <xiaofeng.li@gmail.com> wrote:
>>
>>> Please try with EUT3.5 before committing... :)
>>>
>>> Thanks,
>>> xiaofeng
>>>
>>> On Mon, Jan 5, 2009 at 4:34 PM, chunrong lai <chunronglai@gmail.com>
>>> 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 <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.
>>> >>
>>> >
>>>
>>>
>>>
>>> --
>>>  Managed Runtime Technology Center, Intel
>>>
>>
>
>
>
> --
> Xiao-Feng Li
> Managed Runtime Technology Center, Intel
>

Mime
View raw message