Skip to content

Dynamic class loading and invocation

exotic edited this page Feb 2, 2024 · 1 revision

Dynamic class loading

FOR MORE DETAILED EXAMPLES AND EXPLANATIONS PLEASE REFER TO JSEC
You can find JSec here.

You might find yourself in a situation where you need to load a class into the JVM at runtime. To do this you need to use the java.lang.ClassLoader class (of course there are many ways to load classes in the JVM but this is the most common way).

Here's some example code on setting up a class loader:

try {  
    ClassLoader loader = ClassLoader.getSystemClassLoader();  
    Class<?> klass = loader.loadClass("com.example.MyClass");  
} catch (ClassNotFoundException ignored) {}

loading a class allows you to use it, for example you can load a class using it's bytes and then invoke a method you may need dynamically.

Dynamic method invocation

Dynamic handle-based invocation

Let's say you want to invoke a method from a loaded class (optional) on the spot and you need it to be fast, in this case you can use Java's java.lang.invoke.MethodHandles class.

Here's some example code on throwing down a setup to invoke methods, let's say you have this method you want to invoke:

public class MyClass {
   public void act() {
       // do something.
   }
}

Now you might want to look at the Invocation page to learn how to invoke virtual methods (instance-based invocation).

try {  
     Class<?> klass = Class.forName("com.example.MyClass");  
     MethodHandles.Lookup lookup = MethodHandles.lookup();  
  
     // obtain a handle to the method  
     MethodHandle handle = lookup.findVirtual(  
             klass,  
             "act",  
             MethodType.methodType(void.class)  
     );  
  
     // since our method is virtual we need an instance of it 
     // we also should use klass.getDeclaredConstructor().newInstance()
     // because klass.newInstance() is deprecated
     Object instance = klass.getDeclaredConstructor().newInstance();  
  
     // invoke using instance  
     handle.invoke(instance);  
} catch (Throwable ignored) {  
     ignored.printStackTrace();  
}

Dynamic reflection-based invocation

Reflection is another concept in Java that is easier to perform compared to handle-based invocation but yields worse results as it isn't as fast as handle-based invocation.

Here's an example of how to use reflection:

try {  
     Class<?> klass = Class.forName("com.example.MyClass");  
     Method method = klass.getDeclaredMethod("act");  
     Object instance = klass.getDeclaredConstructor().newInstance();  
     
     // invoke using the instance  
     method.invoke(instance);  
} catch (Throwable ignored) {  
     ignored.printStackTrace();  
}