Summary:
We usually experience some kind of delay if we have to run a java program in any environment. It will take good amount of time to create a process to run the JVM and on top of that load the application classes and execute them. In some documents it is described as a cold start problem.
What if we continuously run a JVM process and dynamically load, execute and unload those classes from JVM. This doesn’t need to create a JVM process and we just need to load and fire those classes.
How this can work?
Every time when we want to execute a piece of java code, load the compiled class files using a new instance of class loader in a JVM. Each class loader instance can act as a container for those loaded application classes. Each instance of the class loader will have its own set of classes and they are part of class loader which is loading them.
(Same class can be loaded multiple times if it loaded by multiple instances of class loaders i.e one for each class loader instance).
Ideally URLClassLoader can be used to load classes from a jar file. And load and execute the required classes. We can unload those classes by simply garbage collecting the newly created classloader instance. This intern, make all those classes loaded by this class loader to be available for GC form metaspace. And metaspace can be cleaned by garbage collectors for loading new classes.
This is analogous to aws lambda’s, but we don’t need to create those JVM processes each time we want to run a piece of java code.
Code
Load the “fatjar” file into the running JVM
Path jarFilePath = FileUtil.saveFile(fileName, multipartFile);
Load the classes using a custom class loader
URL url = jarFilePath.toUri().toURL();
URLClassLoader child = new URLClassLoader(new URL[] { url });
Load the class definition and invoke using following code
Class classToLoad = Class.forName(fullClassName, true, child);
Method method = classToLoad.getDeclaredMethod(methodName);
Object instance = classToLoad.newInstance();
Object result = method.invoke(instance);
Prototype:
The application has been developed using spring boot which is locate at https://bitbucket.org/prabhukvn/tinlet/src/develop/
The above application can be tested with a sample application,
https://bitbucket.org/fastcartservices/tinlet-ts/src
How to test?
Run the tinlet application as a spring boot app and use the following command to test it
curl –location –request POST ‘localhost:8080/tinlet/run’ \
–form ‘file=@”/C:/prabhukvn/projects/tinlet-ts/target/tinlet-ts-0.0.1-SNAPSHOT-jar-with-dependencies.jar”‘ \
–form ‘fullClassName=”com.kvn.tinletts.TinletOne”‘ \
–form ‘methodName=”hello”‘
you can import this command into postman too.
