JDK-4388202 : URLClassLoader fails when a URL points to a JAR inside another JAR
  • Type: Bug
  • Component: tools
  • Sub-Component: jar
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2000-11-10
  • Updated: 2006-02-06
  • Resolved: 2002-05-29
Related Reports
Duplicate :  
Description
Name: yyT116575			Date: 11/10/2000


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


This is a resubmission of the bug following a review (ID 111906). I disagree
with the reviewer's conclusion that this is a duplicate of bug 4110602.

Since the submission, I hunted around a bit in the sources and found that the
source of the bug is the inability of java.net.JarURLConnection to handle
nested jars. There is a comment to that effect in the source.

I believe this bug can be easily fixed without impact. I can post a patch if so
desired.

ORIGINAL BUG REPORT
Say I have a jar, called setup.jar, which contains another jar, app.jar. Here's
the layout:

setup.jar
 +--META-INF
 |  |
 |  \MANIFEST.MF
 |
 +--Bootstrap.class
 |
 \--app.jar
    |
    +--META-INF
    |  |
    |  \MANIFEST.MF
    |
    \--App.class

NOTE: The manifest does not contain a Class-Path: directive. I handle the class
path explicitly by creating a new ClassLoader.

Now I'd like Bootstrap to locate app.jar using Class.getResource(), create a
URLClassLoader using the resulting URL, locate App.class using
ClassLoader.loadClass(), and invoke its main() method. But this fails with an
exception:

Exception in thread "main" java.lang.ClassNotFoundException: App
        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:297)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:253)
        at Bootstrap.main(Bootstrap.java:13)

Here are the sources used:

--------Bootstrap.java-----------

import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class Bootstrap {

	public static void main(String[] args) throws Exception {
		URL app = Bootstrap.class.getResource("/app.jar");
		//URL app = new URL("file:/C:/users/avik/cms/Tip/app.jar");
		System.out.println("app path: " + app);
		ClassLoader loader = new URLClassLoader(new URL[] { app });
		Class entry = loader.loadClass("App");
		Class[] argTypes = new Class[] { new String[0].getClass() };
		Method main = entry.getMethod("main", argTypes);
		main.invoke(null, new Object[] { args } );
	}

}
--------end--------------

-------App.java--------
public class App {
	public static void main(String[] args) {
		System.out.println("Hello, world");
	}
}
--------end-----------

-----app.manifest-------
Manifest-Version: 1.0
Main-Class: Bootstrap
--------end-------------

------testpackage.bat-----------
javac Bootstrap.java App.java
jar c0f app.jar App.class
jar c0mf app.manifest setup.jar app.jar Bootstrap.class
java -jar setup.jar
---------end-----------------

Create all files as specified and run testpackage.bat.
(Review ID: 111955) 
======================================================================

Comments
WORK AROUND Name: yyT116575 Date: 11/10/2000 Extract app.jar into a temporary location. ======================================================================
11-06-2004