<div dir="ltr"><div>Previously, we at Red Hat had done some investigation into static final fields and how existing classes could be adapted to enable their statics to be initialized at build time.  </div><div><br></div><div>I'd like to replay some of that investigation here, both to share our findings and also to gather different perspectives on the problem space.  Our work had been very focused on moving work from runtime to build time and with legitimizing build time initialization - recognizing two phases: build & run time.  With Leyden's approach to shifting constraints there may be different outcomes from these kinds of investigations, especially in light of the recognition that there may be many phases beyond just build and run times.</div><div><br></div><div>I'd like to break the document up into a series of threads on each topic as that often leads to more focused discussion.  I've also posted the full document is available at [0].</div><div><br></div><div>Let's start off with some background on class initialization and a key question: why don't users group their static fields together in ways to give them different lifetimes?  We have tools to do this today, like the IODH pattern, why aren't they used more broadly?</div><div><br></div><div><div>Key question:</div><div>As we look at shifting work from runtime to build time, we should understand what drives user behaviour today.  What tools are available for controlling lifecycles of static fields and how popular are those tools?  Broadly used or narrowly?  Why?<br></div><div></div></div><div><br></div><div>Background:</div><div>Class initialization is a bit of a magic process from the perspective of users. Users typically believe it happens when the class is loaded rather than understanding the actual triggers specified in JVMS { new, get/putstatic, invokestatic, and caused by subclass init, reflection }.<br><br></div><div>Class init is also difficult to reason about because it takes all the static field initializations (apart from those done using the ConstantValue attribute) and puts them together into a single “soupy” method. This method is “soupy” in that it mixes all the interactions and operations - even those expressed separately in the source - into a single method that allows unbounded side effects.<br><br></div><div>To make matters even less clear, the language and VM have slightly different rules for how static final fields are written: At the language level, the compiler enforces that static finals are only written to once but the VM allows them to be written as many times as needed if done within the <clinit> method (this used to be if done from within the defining class).<br><br></div><div>All this results in the life cycle of every static field in a class being conjoined, even if they would be better handled in different life cycles.<br><br></div><div>There is:<br>* One initialization point<br>* One method that is called to write the fields<br>* One duration for all of them (the life of the class or, equivalently, its classloader)<br>* One thread that executes the method (good for exactly once semantics)<br><br></div><div>There is a common case where users recognize these conditions and use them to produce obviously correct code: the initialization-on-demand holder idiom. This is used to create singletons that ensure there is only a single instance of the class, and occasionally used to defer expensive operations until first use (lazy init).<br></div><div><br></div><div>--Dan</div><div><br></div><div>[0] <a href="http://cr.openjdk.java.net/~heidinga/leyden/ClassInitPlan.pdf">http://cr.openjdk.java.net/~heidinga/leyden/ClassInitPlan.pdf</a></div><div><br></div><div><br></div></div>