I am trying to use a custom class loader to load all the dependencies needed for the application. I've implemented the customerClassLoader following the site: https://www.javacodegeeks.com/2013/03/java-handmade-classloader-isolation.html
However, I dont understand how to tell my application to use the custom classLoader whenever needed.
For instance: Lets say, I have a method to make http request like below. How can I tell the application to use the custom classLoader to load the required jars?
private HttpResponse get() {
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
return response;
}
Custom class loaders are useful in larger architectures consisting of several module/applications. Here are the advantages of the custom class loader: Provides Modular architecture Allows to define multiple class loader allowing modular architecture.
Extension ClassLoader searches for the class in the Extension Classpath(JDK/JRE/LIB/EXT). If the class is available then it is loaded, if not the request is delegated to the Application ClassLoader. Application ClassLoader searches for the class in the Application Classpath.
Class loaders are responsible for loading Java classes dynamically to the JVM (Java Virtual Machine) during runtime. They're also part of the JRE (Java Runtime Environment). Therefore, the JVM doesn't need to know about the underlying files or file systems in order to run Java programs thanks to class loaders.
We will create our own ClassLoader by extending the ClassLoader class and overriding the loadClass(String name) method. If the class name will start from com. journaldev then we will load it using our custom class loader or else we will invoke the parent ClassLoader loadClass() method to load the class.
Java uses ClassLoader
implicitly when you use new
, import
keyword, the jvm will use the current class's classloader to load the dependent classes, so you can use the custom classloader to load a bootstrap
class explicitly by using classloader.loadclass
, and the bootstrap
just runs a method belonging to your target class instance. An example follows.
There is a class Target
that depends on the class DateFormatter
which is included in the spring-context
, and has a method named start
.
import org.springframework.format.datetime.DateFormatter;
public class Target {
private static DateFormatter dateFormatter;
public void start(){
System.out.println(this.getClass().getClassLoader());
dateFormatter=new DateFormatter();
System.out.println(dateFormatter);
}
}
Next, we compile and package the above code as a jar named target.jar
, which is stored at D:\\test\\target.jar
.
Next, we declare a class BootStrap
in another jar that will call the method start
of Target
instance. The BootStrap
class will dynamically load the target.jar
and spring-context
jar files by the same classloader
which is a URLClassLoader
instance. Because of this, the method start
in Target
instance can access the DateFormatter
class that is defined in spring-context
.
public class BootStrap {
public static void main(String[] args) throws Exception{
URL url = new URL("http://maven.aliyun.com/nexus/content/groups/public/org/springframework/spring-context/4.3.1.RELEASE/spring-context-4.3.1.RELEASE.jar?spm=0.0.0.0.kG1Pdw&file=spring-context-4.3.1.RELEASE.jar");
URL url2= (new File("D:\\test\\target.jar").toURI().toURL());
URLClassLoader classLoader = new URLClassLoader(new URL[]{url,url2});
Class<?> clz = classLoader.loadClass("com.zhuyiren.Target");
Object main = clz.newInstance();
Method test = clz.getMethod("start");
test.invoke(main);
}
}
Finally, run the BootStrap
main method. There are two important thing:
BootStrap
class and Target
class don't belong to a same jar file.target.jar
is not stored in CLASSPATH
path.These 2 point can make sure that the AppClassLoader
can not find and load the Target
class. Because of the mechanism of class loader, jvm will use the custom load the Target
. Of course, you can guarantee it by changing the URLClassLoader classLoader = new URLClassLoader(new URL[]{url,url2});
to URLClassLoader classLoader = new URLClassLoader(new URL[]{url, url2}, ClassLoader.getSystemClassLoader().getParent());
And we can see the result:
java.net.URLClassLoader@e9e54c2
org.springframework.format.datetime.DateFormatter@4dd8dc3
That means we can access the DateFormatter
instance which is defined in spring-context
jar file successfully, while the spring-context
is not stored in CLASSPATH
, but we are using the custom clasloader to load and use it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With