Prev: setJPEGEncodeParam method not found in JPEGImageEncoder jdk 1.5 and jdk 1.6
Next: HYDROCODONE SIDE EFFECTS INFORMATION
From: Lew on 18 Nov 2009 14:26 Tom Anderson wrote: > We have a class which does some setup in a static block that needs to > happen early in the lifecycle of the app (this is a dubious design, but > there you go - it's largely forced on us from without). Thus, it needs to > get loaded early. We have an initialiser class which runs at a suitable > time, so that's where we'll load the class. What's the best way to do > this? .... > I could just store it in a local: > > void initialise() { > Class foo = Foo.class; > } > > Since i [sic] actually have several classes, i [sic] could put them in an array: > > void initialise() { > Class[] loadedClasses = new Class[] {Foo.class, Bar.class, Baz.class}; > > } > > Am i [sic] right in thinking that all of these will force loading of Foo? > Yes, but not initialization. If all you need is loading, you're fine, but if you need initialization, you're not.. Mere reference to the 'class' literal is forbidden to initialize the class. JLS 12.4.1 <http://java.sun.com/docs/books/jls/third_edition/html/ execution.html#12.4.1> This restriction is enforced in Sun JVMs starting with Java 5. 'Class.forName( String )' is documented to cause initialization but 'Class#getName()' is not so documented. <http://java.sun.com/javase/6/docs/api/java/lang/Class.html#forName (java.lang.String)> <http://java.sun.com/javase/6/docs/api/java/lang/Class.html#getName()> It may be, however, that the latter is one of the "certain reflective methods in class Class" to which the JLS refers, but without explicit documentation of such it's a fragile promise/premise. -- Lew
From: Thomas Pornin on 18 Nov 2009 14:30 According to Tom Anderson <twic(a)urchin.earth.li>: > But that's a bit hackish too. I could just store it in a local: > > void initialise() { > Class foo = Foo.class; > } > > Since i actually have several classes, i could put them in an array: > > void initialise() { > Class[] loadedClasses = new Class[] {Foo.class, Bar.class, Baz.class}; > } > > Am i right in thinking that all of these will force loading of Foo? You are right in that the class Foo will be _loaded_, but that is not what you want. You want the class to be loaded _and_ initialized, and here the Foo class is not initialized. Class initialization occurs upon first "access": read or write to a static field (not counting the pre-initialized final fields of a 'primitive enough' type to be inlined in the caller), call to a static method, or creation of an instance. Note that creating an array of Foo is not sufficient to get the Foo class initialized. The standard JDK does not feature any direct method for initializing a class; the least indirect one is Class.forName() (there are two versions, one of which accepts a boolean which lets you find a class by name without initializing it, the exact opposite of what you are looking for). --Thomas Pornin
From: Thomas Pornin on 18 Nov 2009 14:34 According to Lew <lew(a)lewscanon.com>: > <http://java.sun.com/javase/6/docs/api/java/lang/Class.html#getName()> > > It may be, however, that the latter is one of the "certain reflective > methods in class Class" to which the JLS refers, but without explicit > documentation of such it's a fragile promise/premise. Actually, calling Class.getName() on Sun's JDK 6 is not sufficient to get the class initialized (try it !). --Thomas Pornin
From: Alessio Stalla on 18 Nov 2009 15:56 On 18 Nov, 20:06, Tom Anderson <t...(a)urchin.earth.li> wrote: > On Wed, 18 Nov 2009, Peter Duniho wrote: > > Tom Anderson wrote: > >> [...] > >> Am i right in thinking that all of these will force loading of Foo? > > > I think so. But I haven't checked the spec to make sure. > > >> Does anyone have any other idioms? How about any opinions on which idiom is > >> best, or at least most idiomatic? > > > I find the question ironic. :) The fact is, you've got some clearly > > non-idiomatic scenario, where for some reason your code has managed to become > > dependent on the initialization of a class that it does not in fact refer to > > in the process of being dependent on it. > > > Given that violation of a very fundamental assumption one normally could make > > in a Java program, asking for an idiomatic solution to the violation seems > > sort of silly to me. Your code is already broken; any work-around is > > destined to be non-idiomatic. :) > > What's really happening is more like this: > > class FooMangler implements Mangler { > static { > ManglerRegistry.register("foo", FooMangler.class); > } > > } > > class ManglingParser extends org.xml.sax.helpers.DefaultHandler { > public void startElement (String uri, String localName, String qName, Attributes attrs) throws SAXException { > String manglerName = attrs.getValue("mangler"); > Mangler mangler = ManglerRegistry.lookup(manglerName); > mangler.mangle(qName, attrs); > } > > } > > The idea is that manglers can take care of registering themselves - as > long as they're loaded. This is an old and fairly well-known pattern (at > least, not wildly obscure - in terms of birds, about as common as a > kingfisher is in England), although i certainly wouldn't say it's a good > one, or even a non-dubious one. 'Broken' is a bit too strong, although > only a bit. If you have control on the source code of the mangler, I would do like this: class FooMangler implements Mangler { public static void autoregister() {} ... } and to initialize it, FooMangler.autoregister(); else, Class.forName(FooMangler.class.getName()) is the safest bet: it always initializes the class and fails at compile time if FooMangler is ever renamed (provided that the file containing the Class.forName is recompiled!). Alessio
From: Mike Schilling on 18 Nov 2009 17:50
Tom Anderson wrote: > Hi chaps, > > We have a class which does some setup in a static block that needs > to > happen early in the lifecycle of the app (this is a dubious design, > but there you go - it's largely forced on us from without). Thus, it > needs to get loaded early. We have an initialiser class which runs > at > a suitable time, so that's where we'll load the class. What's the > best way to do this? Add a static method to the class, called e.g. initialize(), and call it. |