On Mon, Jan 5, 2009 at 1:10 PM, Nathan Beyer <[email protected]> wrote: > On Sun, Jan 4, 2009 at 10:08 PM, Xiao-Feng Li <[email protected]> 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. > > 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. Thanks, xiaofeng > -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
