Overview
JCL is a simple Java API that allows loading classes from Jar files. It uses a custom class loader to load classes from JARs, which helps in isolating class loaders and it even makes it possible to load multiple versions of the same class file from different jars. JCL also integrates with Spring; the integration is tested with Spring 2.5.
Installation
To use JCL, download and build the JCL project and put jcl.jar and dependencies in the application's classpath.
Usage
JCL is a light weight API and has only a few but useful classes. Here is a simple example on how to programmatically use JCL. JarClassLoader has an arguments-constructor and add methods that take jar-file/class-folder paths, URLs and InputStreams.
JarClassLoader jcl = new JarClassLoader(); jcl.add("myjar.jar"); //Load jar file jcl.add(new URL("http://myserver.com/myjar.jar")); //Load jar from a URL jcl.add(new FileInputStream("myotherjar.jar")); //Load jar file from stream jcl.add("myclassfolder/"); //Load class folder jcl.add("myjarlib/"); //Recursively load all jar files in the folder/sub-folder(s) JclObjectFactory factory = JclObjectFactory.getInstance(); //Create object of loaded class Object obj = factory.create(jcl,"mypackage.MyClass");
Now in order to invoke the methods of the object one has to use reflection.
Similarly JCL can be used with spring framework.
<!-- Singleton object factory --> <bean id="jclFactory" class="xeus.jcl.JclObjectFactory"></bean> <!-- Test jar class loader --> <bean id="jcl" class="xeus.jcl.JarClassLoader"> <constructor-arg> <list> <value>myjar.jar</value> <ref bean="someJarInputStream"></ref> <ref bean="someJarURL" /><ref></ref> </list> </constructor-arg> </bean> <!-- The Bean arguments: 1- The jar class loader 2- Name of the class to be loaded The rest are optional arguments used in constructor/setter injection for the bean to be loaded --> <bean id="test" factory-bean="jclFactory" factory-method="create"> <!-- Factory-method arguments --> <constructor-arg> <ref bean="jcl"></ref> </constructor-arg> <constructor-arg> <value>mypackage.MyClass</value> </constructor-arg> <!-- Bean arguments --> <constructor-arg> <value>Hello</value> </constructor-arg> <property name="name"> <value>Kamran Zafar</value> </property> </bean>
Casting objects loaded in JCL
Java disallows casting objects loaded in a different classloader; such casting attempt results in a ClassCastException. But sometimes it is necessary to cast objects to obtain interface references loaded in the current classloader. E.g. suppose that an API implementation is loaded using JCL and the API itself is loaded in the current classloader, now it is easy to use the interface reference to invoke methods than using reflection. JCL provides a few ways to obtain interface references and coverting the JCL-loaded objects into castable objects.
JarClassLoader jcl = new JarClassLoader(); jcl.add("myapi-impl.jar"); //Load jar file JclObjectFactory factory = JclObjectFactory.getInstance(); //Create object of loaded class Object obj = factory.create(jcl,"myapi.impl.MyInterfaceImpl"); //Obtain interface reference in the current classloader MyInterface mi = JclUtils.cast(obj, MyInterface.class); //Convert the object into a castable object in the current classloader MyInterface mi1 = (MyInterface) JclUtils.toCastable(obj, MyInterface.class); //Clone "Serializable" object into a castable object in the current classloader //The JCL-loaded object must implement Serializable MyInterface mi2 = (MyInterface) JclUtils.clone(obj);
Manipulating class loading order & adding custom classloaders
JCL as of version 1.3 by default looks for classes in four places in order, local JCL class loader (order=1), current class loader (order=2), parent class loader (order=3) and then in system class loader (order=4). More class loaders can be added by extending the xeus.jcl.loader.Loader class. Each loader has a loading order, the default loading orders can be changed. Below is an example that shows how this loading order can be changed.
JarClassLoader jcl=new JarClassLoader(); jcl.add("myjar.jar"); // Add some class source jcl.getSystemLoader().setOrder(1); // Look for classes in system class loader first jcl.getLocalLoader().setOrder(2); // if not found look for classes in local class loader jcl.getParentLoader().setOrder(3); // if not found look for classes in parent class loader jcl.getCurrentLoader().setOrder(4); // if not found look for classes in current class loader // A custom class loader that extends xeus.jcl.loader.Loader MyLoader loader=new MyLoader(); loader.setOrder(5); jcl.addLoader(loader); //Add custom loader
Resources
- A nice tutorial with examples by Nestor
- Javadoc API for more details.
Downloads
JCL is open source under GPL
and is available for download
on sourceforge. The source can be anonymously checked-out from subversion using
the following command:
svn co https://jcloader.svn.sourceforge.net/svnroot/jcloader/trunk/JCL JCL