United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4735639 : URLClassLoader does not work with jar: URLs

Details
Type:
Enhancement
Submit Date:
2002-08-22
Status:
Open
Updated Date:
2009-03-27
Project Name:
JDK
Resolved Date:
Component:
core-libs
OS:
linux,generic
Sub-Component:
java.net
CPU:
x86,generic
Priority:
P4
Resolution:
Unresolved
Affected Versions:
1.4.1,1.4.2
Targeted Versions:

Related Reports
Relates:

Sub Tasks

Description

Name: nt126004			Date: 08/22/2002


FULL PRODUCT VERSION :
java version "1.4.1-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-rc-b19)
Java HotSpot(TM) Client VM (build 1.4.1-rc-b19, mixed mode)

and 

java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)


FULL OPERATING SYSTEM VERSION :
Linux matrix.piro.net 2.4.19-xfs #3 SMP Mon Aug 5 15:44:31
CEST 2002 i686 unknown

ADDITIONAL OPERATING SYSTEMS :


A DESCRIPTION OF THE PROBLEM :
The URLClassLoader does work with jar: URLs.

Assume, that you have a JAR with the following content:
  C1.class
  x2.jar (which contains C2.class)

C1 needs classes in "jar:file:x1.jar!/x2.jar" - so it
constructs a URLClassLoader with that URL - but the CL does
not find the classes...

Mentioning the JAR URL on the command line using -classpath
or setting it in the Manifest "Class-Path" attribute does
not work at all (no error messages)

The testcase below illustrates the bug.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create the 4 source files (see "Source Code")
2. run test.sh (on Unix or cygwin - I tested it on Linux)


EXPECTED VERSUS ACTUAL BEHAVIOR :
The actual result is a ClassNotFoundException.

I expect classes to be loaded using the URLClassLoader with
jar: URLs.


ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.ClassNotFoundException: C2
	at java.net.URLClassLoader$1.run(URLClassLoader.java:198)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:186)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:299)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:255)
	at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:315)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:217)
	at C1.main(C1.java:10)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
You need 4 files (C1.java, C2.java, manifest and test.sh). Just run test.sh to
reproduce the bug.


C1.java:

import java.net.*;
import java.lang.reflect.*;
public class C1 {
    public static void main(String args[]) throws Throwable {
        System.out.println("C1: first");
        URL u=new URL("jar:file:x1.jar!/x2.jar");
        u.openConnection().getInputStream().close();
        URLClassLoader cl=new URLClassLoader(new URL[]{u});
        System.out.println("C1: second");
        Class cls=Class.forName("C2",true,cl);
        System.out.println("C1: third");
        Method mth=cls.getMethod("main",new Class[]{String[].class});
        mth.invoke(null,new Object[]{args});
    }
}




C2.java:

public class C2 {
    public static void main(String args[]) throws Throwable {
        System.out.println("C2: here I am");
    }
}





manifest:

Main-Class: C1





test.sh:

#!/bin/sh
echo "compiling..."
javac C1.java C2.java
echo "creating x2.jar..."
jar cf x2.jar C2.class
echo "creating x1.jar..."
jar cfm x1.jar manifest C1.class x2.jar
echo "executing..."
java -jar x1.jar

---------- END SOURCE ----------

CUSTOMER WORKAROUND :
I created my own class loader.
(Review ID: 163476) 
======================================================================

                                    

Comments
EVALUATION

It's not really correct to say that URLClassLoader does not work with jar URLs.
What the submitter wants is to be able to load classes from a jar file nested
within another jar file, which is something we do not currently support.

Arguably, the spec for JarURLConnection implies that jar: urls can be nested,
but the implementatation (of URL) does not allow this. Similarly, the JarFile class does not lend itself to nested jar files readily. ie. you have to
read a JarEntry into a File and then create a new JarFile instance from that.
If we were to support reading classes from a nested jar file (even at only
one level of nesting) JarFile and JarEntry would need to support that
behavior directly (without having to create temporary files)

Aside form the generic nesting issue, it is also arguable that JarURLConnection
should support the case where the jar: url points to an entry that is a jar file
(which is the specific case in this report) but supporting this case, also
needs the same support form JarFile and JarEntry as above.
This requirement is documented in bug 4648386.

It seems that with the advent of ear, rar, and war files from J2EE such
nested JAR files are not uncommon, and it would be useful to be able
to load resources from them without having to extract individual archive
members first. 
This issue and 4648386, probably should be targeted for the same release.

###@###.### 2002-08-23
                                     
2002-08-23
EVALUATION

One problem with supporting nested jar files, is how to deal with compression.
Currently, ZipFile (and JarFile) instances are created from random access java.io.File
objects. Entries can be accessed at random, and an InputStream acquired to read the
contents of the entry. If the zip/jar is compressed, then an appropriate inflater or
decompressor is applied to the InputStream returned. 

If we were to support nested jar files, then such nested files could no longer be
accessed in random order (because the data is only available as a stream). Of course, an 
alternative would be to read the contents of the stream into a temporary file and then
use that file as the source for the nested JarFile instance, but in reality there
is nothing to stop applications from employing that kind of strategy today.

In principle, it might be possible to support nested jar files that are not compressed. 
In that case, you could use the same File instance for both the parent JarFile 
and the nested JarFile (with appropriate offsets to distinguish them), 
but precluding the use of compression is too severe a restriction on jar files
to make the feature very useful.

For this reason, it does not seem to be feasible to support this right now.
                                     
2007-06-20



Hardware and Software, Engineered to Work Together