Another Jar Question:

I’ve been using the loadImage (uses Imageio.read(getClass().getResource()) class from the wiki in my java projects lately. I’d been loading images in a jar from an app inside a jar with no problems.

Now I’m working with an applet inside a jar. The jar contains the applet, some misc class files, an image file (.gif), and another jar. The manifest only has ClassPath defined for the jar in the jar. The applet loads and runs fine except the images are smeared.

It makes me think that the getClass.getResource isn’t recognizing the image is in a jar when in fact it is.

The file structure in the jar looks like this:

Manifest.mf
js.jar
applet.class
misc.class
misc.class
image.gif

I hate to go thru the trouble of opening a url connection to a jar file if I don’t have too? I shouldn’t have to, should I?

It should work the same for Applets. Describe “smeared”. If it wasn’t working you should get something like ResourceNotFound or another error loading the image. It sounds like the problem is something else.

This is really bizarre, every time I compile I repack the jar; I run the applet from the source directory and then from the jar using different html. So its the same code giving different results:

http://www.geocities.com/nonnus29/javademo2/smear.gif

I tried putting the image in a subdirectory in the jar and in the sub jar (which the manifest classpath points to) of the jar but all of those give the same result as above. Hmmm…

Edit: You’ll probably have to copy and paste the link. No exceptions and no output to the console.

[quote]I tried putting the image in a subdirectory in the jar and in the sub jar (which the manifest classpath points to)
[/quote]
Sub-jar? You can’t have a jar inside a jar be part of the classpath… the manifest is meant to point to other jars in the same place as the first. And for applet I think you still need an attribute in your Applet tag to download the additional jars.

The example image is interesting… Are you not seeing any exceptions? You aren’t accidently covering one up with an empty catch block or something are you?
The fact that you can see generally correct colours in the bad image tells be that it must be finding the image data some how… but maybe the images are being used before they are loaded, or your images are being corrupted in the jar… maybe even you have classpath issues and the images that work are coming from the current directory instead of the jar somehow? Maybe you are running in different JVMs - like the MS JVM for applets, but the Sun VM for Applications?

Ooops, your right;

So I removed the sub jar and the gif. The applet should have been referencing the gif in the applets home directory and the jar. Everything was fine, the output of the applet was the same for both the jar version and the non-jar version.

Then I placed the gif in a sub directory in the jar (and recompiled) and the smear returns. Weird.

No exceptions are blocked out; my code is the ImageLoader straight from the wiki. Hmm…

The applet is running jre 1.4.2… jdk is 1.4.0 (!)

Damn, I thought I was compiling with jdk 1.4.2 these past months; could that cause a problem?

Starting to sound like a JRE bug to me… maybe you can post a small test case.

I downloaded 1.4.2 and recompiled, no difference. The only thing I’ve been able to find in the docs is this bit about urlclassloader:

[quote]This class loader is used to load classes and resources from a search path of URLs referring to both JAR files and directories. Any URL that ends with a ‘/’ is assumed to refer to a directory. Otherwise, the URL is assumed to refer to a JAR file which will be opened as needed.
[/quote]
So since I’m using JApplet, maybe its giving me a urlclassloader instead of a regular classloader (from getClass.getResource)? If its assuming the data for the gif is in a jar could that explain the misplaced colors?

I’ll try to put something together this evening and post it. Its pretty simple; a JApplet using getClass().getResource() to load an image 1. from the home directory or 2. from a jar.

Here’s a zip with the source:

http://www.geocities.com/nonnus29/javademo2/bug.zip

The demojar.htm runs it from the jar.

Is there any reason why you use getResource() instead of getResourceAsStream()?

[quote]Is there any reason why you use getResource() instead of getResourceAsStream()?
[/quote]
Doh. Not as it is any better. sorry.

This will work though:


InputStream in = getClass().getResourceAsStream(resource);
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
byte buffer[] = new byte[1024];
int bytesRead = -1;
while ((bytesRead = in.read(buffer)) != -1) {
      byteOut.write(buffer, 0, bytesRead);
}
byte imageData[] = byteOut.toByteArray();
BufferedImage src = ImageIO.read(new ByteArrayInputStream(imageData));

So it looks like a bug in imageio. Maybe in MemoryCacheImageInputStream.

The URL returned by getResource() probably does not have an associated codebase with it for the applet, so it won’t work with applets. Use getResourceAsStream() and you should be perfectly fine.

Cas :slight_smile:

[quote]The URL returned by getResource() probably does not have an associated codebase with it for the applet, so it won’t work with applets. Use getResourceAsStream() and you should be perfectly fine.

Cas :slight_smile:
[/quote]

[quote]Is there any reason why you use getResource() instead of getResourceAsStream()?

Doh. Not as it is any better. sorry.
[/quote]
Both Tom and I tried that it gives the same result.

Rereading the first post I see you’re attempting to do something strange as well; you can’t access jars inside jars, if you see what I mean - the only resource you have available is the embedded jar. You’ll have to open the jar and read data out of it in a separate step.

Cas :slight_smile:

[quote]Ooops, your right;

Quote:
The URLs in the Class-Path header are given relative to the URL of the JAR file of the applet or application.

So I removed the sub jar and the gif. The applet should have been referencing the gif in the applets home directory and the jar. Everything was fine, the output of the applet was the same for both the jar version and the non-jar version.
[/quote]
Yep, fixed that problem too.

This is the problem which the zip illustrates:

[quote]Its pretty simple; a JApplet using getClass().getResource() to load an image 1. from the home directory or 2. from a jar.
[/quote]
I’ll try get codebase() and see if that does anything different.

Have tried with other images, and jpgs works correctly. This image: http://home.halden.net/tombr/misc/grass.gif causes a:

It is also influenced by the browser cache. I’ve done the following:

  1. Compile and jar with the working workaround (loading data before sending it to ImageIO)
  2. Open applet in Internet explorer. The image shows correctly.
  3. Change source code to use the bugged imageloader. Compile and jar it.
  4. Reload internet explorer using ctrl+reload. The image shows correcly.
  5. Close all instances of internet exploerer
  6. Opening the same applet again. The image is bugged.

Found it in bug parade:
http://developer.java.sun.com/developer/bugParade/bugs/4764639.html

Apparently its well known, a variation of your workaround is all over the swing tutorial (JApplet + icons). :-/