Search code examples
javaclassloaderstatic-methods

Loading a static method using custom class loader


I've a custom class loader as follows

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class MyClassLoader extends ClassLoader
{
    public String invoke(final String className, final String methodName, final String someString)
    {
        try {
            final ClassLoader classLoader = getClass().getClassLoader();
            final Class loadedClass = classLoader.loadClass(className);
            final Constructor constructor = loadedClass.getConstructor();
            final Object myClassObject = constructor.newInstance();
            final Method method = loadedClass.getMethod(methodName, String.class);
            final Object testStr = method.invoke(myClassObject, someString);
            System.out.println(loadedClass.getClassLoader());
            return (String) testStr;
        }
        catch (final ClassNotFoundException e) {
            e.printStackTrace();
        }
        catch (final Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

and a class named Bus

public class Bus
{
    public static String connection(final String incoming)
    {
        return "Bus " + incoming;
    }
}

and a Tester class to test the code

public class Tester
{

    public static void main(final String[] args) throws InterruptedException
    {
        for (int i = 0; i < 3; i++) {
            final MyClassLoader mcl = new MyClassLoader();
            final String s = mcl.invoke("Bus", "connection", "awesome");
            System.out.println("Tester: " + s);
            Thread.sleep(300);
        }
    }
}

Question: Why does the sysout inside MyClassLoader always print the same object (a.k.a class loader)? What am I doing wrong?

What I want to achieve is for each iteration in the Tester class, I would like the Bus class to be loaded into a new class loader


Solution

  • You need to implement your own class loader rather than just use the System class loader. Here is a rather trivial way that only works if the class file is in the expected directory.

    public class MyClassLoader extends ClassLoader
    {
        @Override
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            try {
                byte b[] = Files.readAllBytes(Paths.get("target/classes/"+name+".class"));
                ByteBuffer bb = ByteBuffer.wrap(b); 
                return super.defineClass(name, bb,null);
            } catch (IOException ex) {
                return super.loadClass(name);
            }
        }
    
    
        public String invoke(final String className, final String methodName, final String someString)
        {
            try {
                final ClassLoader classLoader = this;
    

    ...