Skip to main content

[JAI-IMAGEIO] ImageIO.getImageReadersByFormatName("tiff") returns no readers

9 replies [Last post]
Anonymous

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Thad Humphries

I use JAI and JAI-IMAGEIO in various servlets. I'm using Java 1.5.17
without the JAI or JAI-IMAGEIO installed. I've put jai_codec.jar,
jai_core.jar, and jai_imageio.jar in my WEB-INF/lib directory.

My application runs without a hitch on Tomcat 6.0.14 on a Linux server (and
has run fine for over a year). I have also run it on a Macintosh with
Tomcat 6.0.20.

Today I installed Tomcat 6.0.26 on Linux and tried running my webapp. Under
this version of Tomcat, Iterator returned by
ImageIO.getImageReadersByFormatName("tiff") returns false for hasNext().
What gives?

I realize the quirks of Tomcat may be better answered by those developers,
but I also figure that they are apt to be totally unfamiliar with JAI and
JAI-IMAGEIO.

--
"Hell hath no limits, nor is circumscrib'd In one self-place; but where we
are is hell, And where hell is, there must we ever be" --Christopher
Marlowe, 'Doctor Faustus' (v, 121-24)
[att1.html]

Harald Kuhr

Hi Thad,

On 7. apr. 2010, at 20.09, Thad Humphries wrote:

> I use JAI and JAI-IMAGEIO in various servlets. I'm using Java 1.5.17 without the JAI or JAI-IMAGEIO installed. I've put jai_codec.jar, jai_core.jar, and jai_imageio.jar in my WEB-INF/lib directory.
>
> My application runs without a hitch on Tomcat 6.0.14 on a Linux server (and has run fine for over a year). I have also run it on a Macintosh with Tomcat 6.0.20.
>
> Today I installed Tomcat 6.0.26 on Linux and tried running my webapp. Under this version of Tomcat, Iterator returned by ImageIO.getImageReadersByFormatName("tiff") returns false for hasNext(). What gives?

Are you missing the other JAI ImageIO provided readers, or is it only the TIFF reader? I suspect the web application specific plugins (from WEB-INF/lib) are not picked up by ImageIO. Have you tried putting ImageIO.scanForPlugins() (in a static initializer block)? I think that might help in that case. See http://java.sun.com/javase/6/docs/api/javax/imageio/ImageIO.html#scanForPlugins() for more info.

Also, Java for OS X comes with a TIFFImageReader bundled. But it's not registered by default, so it should not interfere.

Best regards,

--
Harald K

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Thad Humphries

Harald,

I just now fixed it. Someone on the Tomcat Users list suggested I comment
out JreLeakPreventionListener in conf/server.xml. The comment in server.xml
says, "Prevent memory leaks due to use of particular java/javax APIs"

My application seems to run without leaks, but after reloading it via the
Tomcat Manager, the Manager's findleaks servlet prints this message: "The
following web applications were stopped (reloaded, undeployed), but their
classes from previous runs are still loaded in memory, thus causing a memory
leak (use a profiler to confirm):..."

Restarting Tomcat clears this by restarting the JVM.

I'm also told:

There are several attributes that can be toggled on and off in the listener;
you could try those one by one, rather than disabling everything. I suspect
it's this one: appContextProtection.

Doc is near the bottom of this page:
http://tomcat.apache.org/tomcat-6.0-doc/config/listeners.html

but I haven't looked into this yet.

--Thad

On Wed, Apr 7, 2010 at 3:48 PM, Harald Kuhr wrote:

> Hi Thad,
>
> On 7. apr. 2010, at 20.09, Thad Humphries wrote:
>
> > I use JAI and JAI-IMAGEIO in various servlets. I'm using Java 1.5.17
> without the JAI or JAI-IMAGEIO installed. I've put jai_codec.jar,
> jai_core.jar, and jai_imageio.jar in my WEB-INF/lib directory.
> >
> > My application runs without a hitch on Tomcat 6.0.14 on a Linux server
> (and has run fine for over a year). I have also run it on a Macintosh with
> Tomcat 6.0.20.
> >
> > Today I installed Tomcat 6.0.26 on Linux and tried running my webapp.
> Under this version of Tomcat, Iterator returned by
> ImageIO.getImageReadersByFormatName("tiff") returns false for hasNext().
> What gives?
>
> Are you missing the other JAI ImageIO provided readers, or is it only the
> TIFF reader? I suspect the web application specific plugins (from
> WEB-INF/lib) are not picked up by ImageIO. Have you tried putting
> ImageIO.scanForPlugins() (in a static initializer block)? I think that might
> help in that case. See
> http://java.sun.com/javase/6/docs/api/javax/imageio/ImageIO.html#scanForPlugins()for more info.
>
> Also, Java for OS X comes with a TIFFImageReader bundled. But it's not
> registered by default, so it should not interfere.
>
>
> Best regards,
>
> --
> Harald K
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
> For additional commands, e-mail: interest-help@jai-imageio.dev.java.net
>
>

--
"Hell hath no limits, nor is circumscrib'd In one self-place; but where we
are is hell, And where hell is, there must we ever be" --Christopher
Marlowe, 'Doctor Faustus' (v, 121-24)
[att1.html]

Harald Kuhr

Hi Thad,

On 7. apr. 2010, at 22.12, Thad Humphries wrote:

> I just now fixed it. Someone on the Tomcat Users list suggested I comment out JreLeakPreventionListener in conf/server.xml. The comment in server.xml says, "Prevent memory leaks due to use of particular java/javax APIs"
>
> My application seems to run without leaks, but after reloading it via the Tomcat Manager, the Manager's findleaks servlet prints this message: "The following web applications were stopped (reloaded, undeployed), but their classes from previous runs are still loaded in memory, thus causing a memory leak (use a profiler to confirm):..."
>
> Restarting Tomcat clears this by restarting the JVM.

I'm no Tomcat expert, but I think you should be able to avoid class/classloader leaking in one of two ways:

1: Move all the JAI libs from WEB-INF/lib to Tomcat's shared/lib folder. This will make them available for all web apps in the Tomcat instance, but ImageIO will not have any references to classes loaded by your web app. Of course, this only works if you have full control over the environment, but it seems you have, as you already edited server.xml. I've done this before (Tomcat 5-ish I think).

2 (I've never tried this, but in theory it should work): Create a context listener (http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletContextListen...) that explicitly registers and unregisters the required Spis in the IIORegistry (http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/spi/IIORegistry.html) on context initialized/destoyed respectively.

Best regards,

--
Harald K

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Nidel, Mike

I've dealt with this problem in a stable fashion using Harald's #1 option
below, in both Tomcat and Weblogic environments. It sounds like option 2
might work, but there's one thing to keep in mind. If you need to use
any ImageIO plugins -- for example JAI ImageIO tools -- in more than one
webapp, I don't think option 2 will work (or at least will require some
more careful code).

The reason is that there is only one copy of the ImageIO class itself
that gets loaded in the app server -- makes sense, right? Well, let's
say you try to register the TIFF image reader from JAI ImageIO tools
in two different webapps, App A and App B. When A registers, its TIFF
plugin is added to the (singleton) ImageIO class. Then B registers and
its plugin is also added. Now what happens if your other code in B
wants to get a reader for TIFF? There's a possibility it could result
in an attempt to access code that was loaded in A, which from a
ClassLoader perspective is a security violation.

There may be some configurable way around this, I don't know. Another
possibility is that you might be able to write code that deals with
the problem of ImageIO returning the "wrong" reader (i.e. not the
one that was loaded from the current app classloader). If you just
ignore any incorrect readers, you might be able to iterate until
you get the right one. I've never tried this, I'd be curious if it
would work.

Basically the larger problem is with any static variables that are
held in common between multiple applications. ImageIO is just one
example of that, other things might be configuration or
internationalization data that is shared between webapps etc.

Hope this helped. Good luck!

> -----Original Message-----
> From: Harald Kuhr [mailto:harald.kuhr@gmail.com]
> Sent: Thursday, April 08, 2010 6:14 AM
> To: interest@jai-imageio.dev.java.net
> Subject: Re: [JAI-IMAGEIO] ImageIO.getImageReadersByFormatName("tiff")
> returns no readers
>
> Hi Thad,
>
> On 7. apr. 2010, at 22.12, Thad Humphries wrote:
>
> > I just now fixed it. Someone on the Tomcat Users list suggested I
> comment out JreLeakPreventionListener in conf/server.xml. The comment
> in server.xml says, "Prevent memory leaks due to use of particular
> java/javax APIs"
> >
> > My application seems to run without leaks, but after reloading it via
> the Tomcat Manager, the Manager's findleaks servlet prints this
> message: "The following web applications were stopped (reloaded,
> undeployed), but their classes from previous runs are still loaded in
> memory, thus causing a memory leak (use a profiler to confirm):..."
> >
> > Restarting Tomcat clears this by restarting the JVM.
>
> I'm no Tomcat expert, but I think you should be able to avoid
> class/classloader leaking in one of two ways:
>
> 1: Move all the JAI libs from WEB-INF/lib to Tomcat's shared/lib
> folder. This will make them available for all web apps in the Tomcat
> instance, but ImageIO will not have any references to classes loaded by
> your web app. Of course, this only works if you have full control over
> the environment, but it seems you have, as you already edited
> server.xml. I've done this before (Tomcat 5-ish I think).
>
> 2 (I've never tried this, but in theory it should work): Create a
> context listener
> (http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletContextList
> ener.html) that explicitly registers and unregisters the required Spis
> in the IIORegistry
> (http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/spi/IIORegistry.
> html) on context initialized/destoyed respectively.
>
>
> Best regards,
>
> --
> Harald K
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
> For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Harald Kuhr

Hi Mike,

You certainly bring up some important issues about my "option 2". Thanks. So it would probably be easiest and safest to avoid it.

But I wonder, more out of curiosity, shouldn't this be handled by the current IIORegistry implementation?

The documentation says: "Each ThreadGroup will receive its own instance; this allows different Applets in the same browser (for example) to each have their own registry." It's a little unclear to me wether different web apps will have different ThreadGroups. Looking at the source, there will be different registries for different app contexts, and in my mind (or my ideal world ;-), there should be one app context per web app. So web app B should never see web app A's readers and vice versa. But of course, it could be that my understanding of this is all wrong.. :-/

Could you please share some thoughts on this?

Best regards,

--
Harald K

On 8. apr. 2010, at 14.51, Nidel, Mike wrote:

[...]

> It sounds like option 2
> might work, but there's one thing to keep in mind. If you need to use
> any ImageIO plugins -- for example JAI ImageIO tools -- in more than one
> webapp, I don't think option 2 will work (or at least will require some
> more careful code).

>> From: Harald Kuhr [mailto:harald.kuhr@gmail.com]
[...]
>> 2 (I've never tried this, but in theory it should work): Create a
>> context listener
>> (http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletContextList
>> ener.html) that explicitly registers and unregisters the required Spis
>> in the IIORegistry
>> (http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/spi/IIORegistry.
>> html) on context initialized/destoyed respectively.

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Nidel, Mike

Hm. yeah according to the documentation, I would think you'd be right.
However, firsthand experience hasn't shown that to be true. It's easy
to test though. Maybe there have been updates in Java 1.6 or later? I'm
still mainly using 1.5 most places.

I went back and looked at places in the ImageIO class and I don't see
how it could be maintaining multiple registries.

public static void scanForPlugins() {
theRegistry.registerApplicationClasspathSpis();
}

There is only one registry stored there, so unless you somehow maintain
your own registries (is that even possible?) then if your app goes through
the ImageIO static methods you might be stuck.

> -----Original Message-----
> From: Harald Kuhr [mailto:harald.kuhr@gmail.com]
> Sent: Thursday, April 08, 2010 9:51 AM
> To: interest@jai-imageio.dev.java.net
> Subject: Re: [JAI-IMAGEIO] ImageIO.getImageReadersByFormatName("tiff")
> returns no readers
>
> Hi Mike,
>
> You certainly bring up some important issues about my "option 2".
> Thanks. So it would probably be easiest and safest to avoid it.
>
> But I wonder, more out of curiosity, shouldn't this be handled by the
> current IIORegistry implementation?
>
> The documentation says: "Each ThreadGroup will receive its own
> instance; this allows different Applets in the same browser (for
> example) to each have their own registry." It's a little unclear to me
> wether different web apps will have different ThreadGroups. Looking at
> the source, there will be different registries for different app
> contexts, and in my mind (or my ideal world ;-), there should be one
> app context per web app. So web app B should never see web app A's
> readers and vice versa. But of course, it could be that my
> understanding of this is all wrong.. :-/
>
> Could you please share some thoughts on this?
>
>
> Best regards,
>
> --
> Harald K
>
> On 8. apr. 2010, at 14.51, Nidel, Mike wrote:
>
> [...]
>
> > It sounds like option 2
> > might work, but there's one thing to keep in mind. If you need to use
> > any ImageIO plugins -- for example JAI ImageIO tools -- in more than
> one
> > webapp, I don't think option 2 will work (or at least will require
> some
> > more careful code).
>
>
> >> From: Harald Kuhr [mailto:harald.kuhr@gmail.com]
> [...]
> >> 2 (I've never tried this, but in theory it should work): Create a
> >> context listener
> >>
> (http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletContextList
> >> ener.html) that explicitly registers and unregisters the required
> Spis
> >> in the IIORegistry
> >>
> (http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/spi/IIORegistry.
> >> html) on context initialized/destoyed respectively.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
> For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Harald Kuhr

On 8. apr. 2010, at 16.00, Nidel, Mike wrote:

> I went back and looked at places in the ImageIO class and I don't see
> how it could be maintaining multiple registries.
>
> public static void scanForPlugins() {
> theRegistry.registerApplicationClasspathSpis();
> }
>
>
> There is only one registry stored there, so unless you somehow maintain
> your own registries (is that even possible?) then if your app goes through
> the ImageIO static methods you might be stuck.

Ouch... I'm afraid you are right. If instead all accesses to theRegistry was replaced with IIORegistry.getDefaultInstance() it might just have worked...

Perhaps I should file a bug then, as the documentation seems to indicate otherwise.

Thanks for pointing it out, anyway! :-)

--
Harald K
---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Nidel, Mike

yeah, sounds like a bug based on the documentation.

there's another bug in there, unless it's been fixed. the registry
doesn't trap exceptions thrown when loading a plugin, so if you
have a bug in your imageIO plugin you can kill all of ImageIO. it's
even possible to get a NoClassDefFoundError on javax.imageio.ImageIO!
that gave me a good chuckle.

But basically they need a try/catch around each plugin load down in
the IIORegistry.

> -----Original Message-----
> From: Harald Kuhr [mailto:harald.kuhr@gmail.com]
> Sent: Thursday, April 08, 2010 10:16 AM
> To: interest@jai-imageio.dev.java.net
> Subject: Re: [JAI-IMAGEIO] ImageIO.getImageReadersByFormatName("tiff")
> returns no readers
>
>
> On 8. apr. 2010, at 16.00, Nidel, Mike wrote:
>
> > I went back and looked at places in the ImageIO class and I don't see
> > how it could be maintaining multiple registries.
> >
> > public static void scanForPlugins() {
> > theRegistry.registerApplicationClasspathSpis();
> > }
> >
> >
> > There is only one registry stored there, so unless you somehow
> maintain
> > your own registries (is that even possible?) then if your app goes
> through
> > the ImageIO static methods you might be stuck.
>
> Ouch... I'm afraid you are right. If instead all accesses to
> theRegistry was replaced with IIORegistry.getDefaultInstance() it might
> just have worked...
>
> Perhaps I should file a bug then, as the documentation seems to
> indicate otherwise.
>
>
> Thanks for pointing it out, anyway! :-)
>
> --
> Harald K
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
> For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net