Prev: setJPEGEncodeParam method not found in JPEGImageEncoder jdk 1.5 and jdk 1.6
Next: HYDROCODONE SIDE EFFECTS INFORMATION
From: Arne Vajhøj on 18 Nov 2009 19:17 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? > > Before i came to it, the code looked like: > > void initialise() { > Class.forName("com.example.Foo"); > } > > I didn't like that, because it's using a string constant where it could > be using something strongly typed, and so not getting enabling > refactoring and inspection in the IDE. I had a bit of a debate with my > pair, and we changed it to: > > void initialise() { > Class.forName(Foo.class.getName()); > } > > Which works, solves the problem, and is clearly bonkers. > > What's a good idiom? One option would be to call a no-op method on the > class literal: > > void initialise() { > Foo.class.getName(); > } > > 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? Does > anyone have any other idioms? How about any opinions on which idiom is > best, or at least most idiomatic? I don't think the problem is common enough to make a solution idiomatic. I would without thinking twice: - read class names from config file - use Class.forName to initialize them Arne
From: Kevin McMurtrie on 19 Nov 2009 02:05 In article <alpine.DEB.1.10.0911181804020.21986(a)urchin.earth.li>, Tom Anderson <twic(a)urchin.earth.li> 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? > > Before i came to it, the code looked like: > > void initialise() { > Class.forName("com.example.Foo"); > } > > I didn't like that, because it's using a string constant where it could be > using something strongly typed, and so not getting enabling refactoring > and inspection in the IDE. I had a bit of a debate with my pair, and we > changed it to: > > void initialise() { > Class.forName(Foo.class.getName()); > } > > Which works, solves the problem, and is clearly bonkers. > > What's a good idiom? One option would be to call a no-op method on the > class literal: > > void initialise() { > Foo.class.getName(); > } > > 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? Does > anyone have any other idioms? How about any opinions on which idiom is > best, or at least most idiomatic? > > Thanks, > tom You can access a non-optimizable static field or static method. A constructor for an instance of the class is the safest bet. Self-registering classes are not the best design. Under extremely rare circumstances, references from live classes to the registration container might not exist during a GC - then it's suddenly empty. In a web server or other application with multiple ClassLoaders, it might not be clear where things are going. For the work I've done, there were enough problems to justify not using JDBC driver self-registration with DriverManager. Consider a configuration parameter that is a list of classes that your registration container should load when it initializes. -- I won't see Goolge Groups replies because I must filter them as spam
From: Roedy Green on 19 Nov 2009 13:10 How about a dummy loadEarly/init static method that does nothing or triggers static init code. -- Roedy Green Canadian Mind Products http://mindprod.com Finding a bug is a sign you were asleep a the switch when coding. Stop debugging, and go back over your code line by line.
From: Jim Janney on 19 Nov 2009 13:40 Tom Anderson <twic(a)urchin.earth.li> writes: > 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. To me what smells here is that ManglerRegistry is using static methods. I'd prefer creating an instance of ManglerRegistry, registering the appropriate manglers with it, and keeping a reference to it in the ManglingParser. This requires more coding, obviously, but gives you more flexibility in that different parsers can use different registries. Also, it allows registering the same mangler more than once under different names, which can sometimes be useful. -- Jim Janney
From: Tom Anderson on 19 Nov 2009 16:00
On Wed, 18 Nov 2009, Lew wrote: > 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> Aha! I had no idea this was the case! Thanks, and thanks to everyone else who pointed it out. > 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. Quite so! tom -- Tubes are the foul subterranean entrails of the London beast, stuffed with the day's foetid offerings. -- Tokugawa |