Loading jars with URLClassLoader

If I use the following code to load a jar file:

URLClassLoader loader = URLClassLoader.newInstance(new URL[] {new URL(“file:/C:\Myjar.jar”)});

Isn’t this supposed to add the loaded jar to the current classpath?

When I try to use this I get a ClassNotFoundException when trying to create an instance from a class in the jar.

Not to the current class path but to the class path of the class loader you’ve created.

So to create the class you’d have to do something like:


Class clazz = loader.loadClass("mypackage.MyClass");
clazz.newInstance();

Not really sure what the problem is. I assume you’ve checked your spelling and the classname does match that in the jar.

You are getting the default parent classloader and creating a new classloader that adds to that path. However, this doesn’t replace the default loader unless you set the Thread’s classloader.
http://java.sun.com/products/jndi/tutorial/beyond/misc/classloader.html
That can fail, if you are in the sandbox.

You can of course get an instance of a class from that classloader by using its loadClass() or findClass() methods. I’m assuming you are doing that - although in that case I’m not sure why you are concerned about it being added to the parent classloader’s path. I have used findClass() to create instances of platform specific classes by name from separate jars, to avoid class not found errors when loading my app on a platform that doesn’t have those libraries.

There’s also this bug, although this is really obscure…
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6220698

This is how I add a class URL at runtime:

store old classLoader:


oldACL = Thread.currentThread().getContextClassLoader();

add new jar URL from working directory:

Util.addClassURL(Thread.currentThread().getContextClassLoader().getResource("resources/add.jar"));

addClassURL function:


    public static void addClassURL(URL u) throws IOException {
    	URL urls[] = new URL[ ]{ u };
    	ClassLoader aCL = Thread.currentThread().getContextClassLoader();
    	URLClassLoader aUrlCL = new URLClassLoader(urls, aCL);

    	Thread.currentThread().setContextClassLoader(aUrlCL);
    }

restore old classLoader:

Thread.currentThread().setContextClassLoader(oldACL);

Ok, thanks guys. I’ll look at that stuff.

What I am trying to do is create a plugin system. So all the user has to do is drop the jar and an XML file in a certain place and my program will automatically load it.

You probably don’t want those classes in your ‘global’ clasdsloader, because you can’t get them out of there.

Just make a URLClassLoader with the ‘global’ ClassLoader as parent, and call loadClass() to get your plugin implementations. Whn you want to replace a plugin, just create a new classloader, from a new jar, with the same classnames.

Unfotunately, it is very recommended, to keep the JAR that is associated with your ClassLoader around. Otherwise, the JVM might crash, an most certainly will (!!). I think the JVM uses MappedByteBuffers and simply loads a new page in RAM whether the backing file has changed or not, then executes (?) the bytes - and there you have it, a native crash.

So either write your own classloader that grabs the whole JAR and keeps in it memory, or simply ensure you never overwrite or delete a JAR you’re using (copy all JARs to /tmp/ with a random name…?).