Sunday, March 8, 2009

URL access to nested .jar files

Tonight I implemented loading of classes from nested jar files. It seems to me that people might be interested in such trick, so here you are.

I created new protocol handler jarjar: which just redirects inner part of URL to .jar handler again. Please note that I use '^/' as jar-in-jar separator to avoid conflict with regular jar handler.

Let's have Outer.jar which contains Inner.jar which contains tested/robots/Ahead.class
Now you can do this
// initialize, just once per JVM please
JarJarURLConnection.register();

new URL(
"jar:jarjar:file:/C:/mylibs/Outer.jar^/Inner.jar!/tested/robots/Ahead.class"
).openStream();
Or create and configure ClassLoader this way
// initialize, just once per JVM please
JarJarURLConnection.register();

new URLClassLoader(
  new URL[]{new URL("jar:jarjar:file:/C:/mylibs/Outer.jar^/Inner.jar!/")}
).loadClass("tested.robots.Ahead");
If you need something more sophisticated or user friendly One-JAR is the solution I think.

2 comments:

Steven said...

Thank you, this was exactly what I was looking for. Solved my problem!!

Anonymous said...

Could you post a way to do this without using the static URL.setURLStreamHandlerFactory(new JarJarURLStreamHandlerFactory()) method? That isn't going to work in any situation where you don't have full control over who calls this global method.

I'm thinking that the same thing could be acheived with the URL constructor that takes the URLStreamHandler param, i.e.

URL(URL context, String spec, URLStreamHandler handler)

but it isn't working for me for some reason.