Showing posts with label Java Classloader concept. Show all posts
Showing posts with label Java Classloader concept. Show all posts

Java Classloader concept | java class loader tutorial

Java ClassLoader

  1.     Java classloader is part of java runtime environment that dynamically loads java class in to java virtual machine.
  2.   Usually classes are loaded on demand.
  3. Java provides ClassLoader abstract class to extend class loading function.
  4.   User defined class loader should do basic functions as: Given the name of the class, a class loader attempt to locate or generate data that constitutes a definition for a class.
  5. Every class object contains reference to the classloader.

        TestLoad.class.getClassLoader()

 Class objects for Array classes are not created by class loader, but are created automatically by java runtime.
    ClassLoader uses delegation model to search for classes and resources.
    Method defineClass() converts an array of bytes in to instance of class.

cls = defineClass(className, classBytes, 0, classBytes.length);

    Various class loaders

Bootstrap Class Loader : Loads classes from JAVA_HOME/lib
Extension Class Loader (sun.misc.launcher$ExtClassLoader): Loads classes from extension directory.
System Class Loader (sun.misc.launcher$AppClassLoader): Loads classes from java.class.path.

    Methods to remember:

findClass(String name) : finds specified class
getParent(): Returns parent class loader for delegation.
getSystemClassLoader(): returns system classloader for delegation.
loadClass(): loads class with specified name.
resolveClass().

     User defined classloader needs permission to load system classes.

method to use defineClass(String name, byte[] b, int off, int len, ProtectionDomain domain).

Write custom class loader.
1) Create class which extends ClassLoader.
2) Override protected synchronized method LoadClass().
3) Use findLoadedClass() to identify if class is already loaded.
4) Handle security exception. for the system classes.
5) In case of security exception, call super.loadClass(). delegate to super classloader.
4) Create test class file.
5) Read the file as byte array.
6) Call define class method.

package classLoader;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class MyClassLoader extends ClassLoader {
 private static final int BUFFER_SIZE = 8192;

 protected synchronized Class loadClass(String className, boolean resolve)
   throws ClassNotFoundException {

  // 1. is this class already loaded?
  Class cls = findLoadedClass(className);
  if (cls != null) {
   System.out.println("Class is already available..");
   return cls;
  }

  // 2. get class file name from class name
  String clsFile = className.replace('.', '/') + ".class";

  // 3. get bytes for class
  byte[] classBytes = null;
  try {
   InputStream in = getResourceAsStream(clsFile);
   byte[] buffer = new byte[BUFFER_SIZE];
   ByteArrayOutputStream out = new ByteArrayOutputStream();
   int n = -1;
   while ((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) {
    out.write(buffer, 0, n);
   }
   classBytes = out.toByteArray();
  } catch (IOException e) {
   System.out.println("ERROR loading class file: " + e);
  }

  if (classBytes == null) {
   throw new ClassNotFoundException("Cannot load class: " + className);
  }

  // 4. turn the byte array into a Class
  try {
  
   cls = defineClass(className, classBytes, 0, classBytes.length);
   if (resolve) {
    resolveClass(cls);
   }
   System.out.println("Loaded using CUSTOM class loader..:"+cls);
  } catch (SecurityException e) {
   cls = super.loadClass(className, resolve);
   System.out.println("Loaded using SYSTEM class loader..:"+cls);
  }

  return cls;
 }
}



package classLoader;

public class TestClassLoader {
 public static void main(String[] args) throws Exception {
        MyClassLoader loader1 = new MyClassLoader();
        Class testLoad = Class.forName("classLoader.TestLoad", true, loader1);
        System.out.println("TestLoad class: " + testLoad);
        if (TestLoad.class.equals(testLoad)) {
            System.out.println("TestLoad loaded through custom loader is the same as that loaded by System loader.");
        }
        else {
            System.out.println("TestLoad loaded through custom loader is NOT same as that loaded by System loader.");
        }
        java.lang.reflect.Method main = testLoad.getMethod("main",
                                                new Class[] {String[].class});
        main.invoke(null, new Object[]{ new String[]{} });
    }
}