Sunday, 12 February 2017

Java ClassLoader


All class files in application are not loaded into memory at startup, but are loaded on demand as needed by the program, this loading of class is done by ClassLoader. ClassLoader is a part of JVM that loads classes into memory.

ClassLoader in Java works on three principle:
Delegation - Delegation principle forward class loading request to parent class loader and only loads the class, if parent is not able to find or load class.

Visibility - Visibility principle allows child class loader to see all the classes loaded by parent ClassLoader, but parent class loader cannot see.

Uniqueness - Uniqueness principle allows to load a class exactly once, which is basically achieved by delegation and ensures that child ClassLoader doesn't reload the class already loaded by parent.

Type of ClassLoader –

There are three default class loader used in Java.

1.      Bootstrap – Bootstrap class loader loads the core java library located in the (<JAVA_HOME>/jre/lib). It is a Super class loader. It loads the Core classes of Java like class in java.lang, java.util package.

2.    Extension – Extension class loader loads the code in the extension directories (<JAVA_HOME>jre/lib/ext) or any other directory specified by the (java.ext.dirs) system property. It implements by the sun.misc.Launcher$ExtClassLoader class

3.    System or Application class loader – The system class loader loads the code found on java.class.path which maps to the classpath environment variable. This is implemented by the sun.misc.Launcher$AppClassLoader

Develoeper can also create Custom class according to their need.

See below code snippet for custom class loader:

public class ClassLoaderTest {

     public static void main(String[] args) {
           Thread thread = Thread.currentThread();
           ClassLoader classLoader = thread.getContextClassLoader();
           try {
                ClassLoaderImpl classLoaderImpl = new ClassLoaderImpl();
               thread.setContextClassLoader(classLoaderImpl);
               System.out.println("Loaded class context is "+thread.getContextClassLoader());
           } finally {
               thread.setContextClassLoader(classLoader);
           }
           System.out.println("Loaded class context is "+thread.getContextClassLoader());
     }
}

class ClassLoaderImpl extends ClassLoader {
     public ClassLoaderImpl() {
           super();
     }
     /*
     * custom code for class loader
     */
}



package com.mk.test.basics;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;

public class TestMain {

   
public static void main(String[] args) throws Exception {
        CustomClassLoader loader =
new CustomClassLoader();
        Class<?> classObj = loader.findClass(
"com.mk.test.basics.TestMain");
        Object object = classObj.newInstance();
        Method method = classObj.getMethod(
"hello");
        method.invoke(object);
    }
   
public void hello(){
        System.
out.println("Hello MK Study Journal!");
    }
}

class CustomClassLoader extends ClassLoader{
   
public Class<?> findClass(String classPath) {
       
byte[] bytes = loadClassData(classPath);
       
return defineClass(classPath, bytes, 0, bytes.length);
    }
   
private byte[] loadClassData(String className) {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(className.replace(
".", "/")+".class");
       
byte byteArray[] = null;
       
try {
            byteArray =
new byte[inputStream.available()];
            DataInputStream dataStream =
new DataInputStream(inputStream);
            dataStream.readFully(byteArray);
            dataStream.close();
        }
catch (IOException e) {
            e.printStackTrace();
        }
       
return byteArray;
    }
}


1 comment: