Say I have a class named NameGenerator
. I can use this to generate names according to a given logic. Then I write a TestNameGeneration
class with a method that asks for a letter from the user and generate a name in accordance. Now I want to change the logic in NameGeneration
class and apply that particular change without stopping the application.
I did this to learn more about class loaders and can someone please explain the key concepts that I have to learn to do something like that or site any references ?
Once a Java class has been loaded by a class loader, it's immutable and will last as long as the class loader itself. The identity is the class name and class loader identity, so to reload an application, you'll need to create a new class loader which in turn will load the latest version of the app classes.
The Java ClassLoader is a part of the Java Runtime Environment that dynamically loads Java classes into the Java Virtual Machine. The Java run time system does not need to know about files and file systems because of classloaders. Java classes aren't loaded into memory all at once, but when required by an application.
To end a Java program, we can use the exit() method of the System class. It is the most popular way to end a program in Java. System. exit() terminates the Java Virtual Machine(JVM) that exits the current program that we are running.
Here is a working test. Every 5 secs Test.main() reloads test.Test1.class from the file system and calls Test1.hello()
package test; public class Test1 { public void hello() { System.out.println("Hello !"); } } public class Test { static class TestClassLoader extends ClassLoader { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { if (name.equals("test.Test1")) { try { InputStream is = Test.class.getClassLoader().getResourceAsStream("test/Test1.class"); byte[] buf = new byte[10000]; int len = is.read(buf); return defineClass(name, buf, 0, len); } catch (IOException e) { throw new ClassNotFoundException("", e); } } return getParent().loadClass(name); } } public static void main(String[] args) throws Exception { for (;;) { Class cls = new TestClassLoader().loadClass("test.Test1"); Object obj = cls.newInstance(); cls.getMethod("hello").invoke(obj); Thread.sleep(5000); } } }
Run it. Then change and recompile Test1
System.out.println("Hello !!!");
while Test is running. You will see Test1.hello output changed
... Hello ! Hello ! Hello !!! Hello !!!
This is how eg Tomcat reloads webapps. It has a separate ClassLoader for each webapp and loads a new version in a new ClassLoader. The old one is GCed just like any Java object as well as the old classes.
Note that we loaded Test1 with TestClassLoader and invoked its first method with reflection. But all Test1 dependencies will be implicitly loaded with Test1 class loader, that is all the Test1 application will be loaded by JVM into TestClassLoader.
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