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)? 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? -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 >
