|jai-...@javadesktop.org||May 31, 2007 5:36 pm|
|jai-...@javadesktop.org||May 31, 2007 5:56 pm|
|Nidel, Mike||Jun 1, 2007 7:03 am|
|jai-...@javadesktop.org||Jun 1, 2007 5:01 pm|
|jai-...@javadesktop.org||Jun 3, 2007 9:11 am|
|Nidel, Mike||Jun 4, 2007 8:31 am|
|jai-...@javadesktop.org||Jun 4, 2007 10:52 am|
|Nidel, Mike||Jun 4, 2007 11:27 am|
|jai-...@javadesktop.org||Jun 4, 2007 2:10 pm|
|jai-...@javadesktop.org||Jun 4, 2007 3:15 pm|
|jai-...@javadesktop.org||Jun 4, 2007 3:58 pm|
|Brian Burkhalter||Jun 4, 2007 4:05 pm|
|jai-...@javadesktop.org||Jun 4, 2007 4:13 pm|
|Nidel, Mike||Jun 5, 2007 6:05 am|
|Subject:||RE: RE: [JAI-IMAGEIO] Re: NoClassDefFoundError:|
|From:||Nidel, Mike (mike...@lmco.com)|
|Date:||Jun 4, 2007 8:31:54 am|
I realized my original question about Class.forName() didn't really have a point. Sorry for the diversion. One thing I should have asked and which you may have already explained: does this error break your application?
I think it is exactly the SPI-style plugins that are killing your app -- however, not necessarily your own but the ones that are in JAI ImageIO Tools. We have seen this kind of thing numerous times because of reflection that is used by plugin lookup. For my team, it's mainly happened in a J2EE app container because of the security boundaries they put on classloaders. It seems logical to me that WebStart might do something similar. What would be an interesting test would be to run your app from the command line (no WebStart), with JAI ImageIO Tools on the system classpath and JAI on your app's own classpath.
I've just spent some time formulating a theory with a coworker as to the cause of the problem, and I think I can guess pretty closely as to what it is.
In the configuration that is causing you problems, you have ImageIO Tools in the JRE lib/ext directory, and JAI in your application. Let's guess that there are separate classloader pools for these two sets of libraries, and there is a one-way classloader reference relationship between them. The result is that classes in your app can "see" (load/reference/use) classes in the JRE. But the core JRE classes (including lib/ext) are loaded in such a way that they cannot see your application's classes. Let's call these the app classloader (ACL) and JRE classloader (JCL) just for simplicity.
In terms of legal references, you have the following:
ACL -> JCL: yes JCL -> ACL: no and of course ACL -> ACL: yes JCL -> JCL: yes
Now in this configuration, you do Class.forName("...JAI"). From your original stack trace, this successfully makes it into the JAI static initializer, because your class is in the ACL and can see JAI (also in the ACL). During static initialization of the JAI class, it sets up the OperationRegistry. This results in a SPI-type lookup (remember what I said at the beginning about plugins). If you look in the JAI ImageIO Tools jai_imageio.jar under META-INF/services, you'll see a descriptor file for OperationRegistrySpi. This references the class com.sun.media.jai.imageioimpl.ImageReadWriteSpi (part of JAI ImageIO Tools of course). This provides the JAI "imageread" and "imagewrite" operators.
So now, during the static initialization of the JAI class, we have started to load the JAI ImageIO Tools code, _which is in the JCL_ (because of the fact that JAI IIO Tools is in the JRE). In a sense, classloader control has moved from the ACL to the JCL. Now under the JCL, the ImageReadWriteSpi class is being initialized. But as you might have guessed, this class implements the OperationRegistrySpi interface, which is a JAI interface. This means you have a hidden dependency BACK from the JCL to the ACL. If you accept my proposal that the classloaders in WebStart are set up in such a way that this is not permitted, then you will see why you get this error: because classes loaded from the JCL cannot "see" classes in the ACL. This is a security constraint, I can't necessarily explain the reasoning but I've seen this kind of problem before in non-WebStart environments and I think the logic of my explanation holds tight. (it's worth noting that your stack trace does go through the SecurityManager, by the way.)
As far as I can tell, the only symptom you should see of this problem is that the ImageWrite and ImageRead operations provided in JAI IIO Tools won't work. This is why I asked above if your application breaks when you see this error, or if it's just a stack trace on the console, or what.
As far as what to do about it... the picture is pretty bleak. I don't think you'll get the behavior of classloaders to change any time this decade (and arguably the classloader is doing the right thing). The most I can say is that you have to instruct your users either to install both JAI and JAI ImageIO Tools, or neither. There MIGHT be something the JAI IIO Tools team could do to make the system more robust to this kind of failure, but that seems to be about it.
Without knowing the real behavior of the WebStart classloader hierarchy, I've made some assumptions here that could be wrong. But the evidence seems to bear them out. If anyone has any more input, feel free to throw it in the ring.
-----Original Message----- From: jai-...@javadesktop.org [mailto:jai-...@javadesktop.org] Sent: Sunday, June 03, 2007 12:12 PM To: inte...@jai-imageio.dev.java.net Subject: Re: RE: [JAI-IMAGEIO] Re: NoClassDefFoundError:
When you do a Class.forName() are you calling it just like that, or are you doing SomeAppClass.class.forName()
I am doing Class.forName("path.of.class")
Do my theories make any sense?
it'll be interesting to see the outcome. The application I am writing uses SPI-style plugins. They've worked well so far, but this ClassLoader difference might become a limiting factor. [Message sent by forum member 'russelleast' (russelleast)]