NOTE

Custom Class Loader

When a custom class loader is needed, how to implement one with findClass or loadClass, an example, and a reference.

JavaCreated Updated 1 min readhistorical

This is a historical learning note and may contain outdated or incomplete understanding.

1. When Is a Custom Class Loader Needed?

  • Load class files from arbitrary paths, such as paths outside the classpath.
  • Isolate class loading. This allows classes with the same name from different applications to be loaded, for example in Tomcat.

2. How to Define a Custom Class Loader

  1. Extend the ClassLoader parent class.
  2. Override methods of the parent class.
    1. If using the parent-delegation mechanism, override findClass.
      1. Read the bytecode of the class file.
      2. Call the parent class’s defineClass method to load the class.
    2. If not using the parent-delegation mechanism, override loadClass.
  3. The caller invokes the class loader’s loadClass method.

3. Example

  • Prepare a Java class and compile it into a class file.
public class MyClass
{
    public MyClass()
    {
        System.out.println("hello, world!");
    }
}
  • Custom class loader
public class MyClassLoader extends ClassLoader
{

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException
    {
        MyClassLoader classLoader = new MyClassLoader();

        Class<?> myClass = classLoader.loadClass("MyClass");
        Class<?> myClass2 = classLoader.loadClass("MyClass");

        System.out.println(myClass == myClass2);// true


        myClass.newInstance();// Prints hello, world!

        MyClassLoader classLoader2 = new MyClassLoader();
        Class<?> myClass3 = classLoader2.loadClass("MyClass");

        System.out.println(myClass == myClass3);// false. A class can be uniquely identified only by class loader + package name + class name


    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException
    {
        String path = String.format("C:\\Users\\[user]\\Desktop\\%s.class", name);
        try
        {

            // Load the class file at the specified path and convert it into bytes
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            Files.copy(Paths.get(path), outputStream);
            byte[] bytes = outputStream.toByteArray();

            // Call the parent class's defineClass method
            return defineClass(name, bytes, 0, bytes.length);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            throw new ClassNotFoundException("Class file not found", e);
        }
    }
}

4. Reference

Discussion

Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub