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
