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