Showing posts with label Class Loaders. Show all posts
Showing posts with label Class Loaders. Show all posts

How to call getClass() from a static method in Java?

Just use TheClassName.class instead of getClass().


Non-Static

InputStream inputStream = getClass().getClassLoader()
                    .getResourceAsStream(FILE_NAME);

 Static

InputStream inputStream = ClassName.class.getClassLoader()
                    .getResourceAsStream(FILE_NAME);

Writing Custom Class Loaders in Java

Building a SimpleClassLoader

A class loader starts by being a subclass of java.lang.ClassLoader. The only abstract method that must be implemented is loadClass(). The flow of loadClass() is as follows:

  • Verify class name.
  • Check to see if the class requested has already been loaded.
  • Check to see if the class is a "system" class.
  • Attempt to fetch the class from this class loader's repository.
  • Define the class for the VM.
  • Resolve the class.
  • Return the class to the caller.

import java.util.Hashtable;
import util.ClassFile;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;

public class SimpleClassLoader extends ClassLoader {
    private Hashtable classes = new Hashtable();

    public SimpleClassLoader() {
    }

    /**
     * This sample function for reading class implementations reads
     * them from the local file system
     */
    private byte getClassImplFromDataBase(String className)[] {
     System.out.println("        >>>>>> Fetching the implementation of "+className);
     byte result[];
     try {
         FileInputStream fi = new FileInputStream("store\\"+className+".impl");
         result = new byte[fi.available()];
         fi.read(result);
         return result;
     } catch (Exception e) {

         /*
          * If we caught an exception, either the class wasnt found or it
          * was unreadable by our process.
          */
         return null;
     }
    }

    /**
     * This is a simple version for external clients since they
     * will always want the class resolved before it is returned
     * to them.
     */
    public Class loadClass(String className) throws ClassNotFoundException {
        return (loadClass(className, true));
    }

    /**
     * This is the required version of loadClass which is called
     * both from loadClass above and from the internal function
     * FindClassFromClass.
     */
    public synchronized Class loadClass(String className, boolean resolveIt)
     throws ClassNotFoundException {
        Class result;
        byte  classData[];

        System.out.println("        >>>>>> Load class : "+className);

        /* Check our local cache of classes */
        result = (Class)classes.get(className);
        if (result != null) {
            System.out.println("        >>>>>> returning cached result.");
            return result;
        }

        /* Check with the primordial class loader */
        try {
            result = super.findSystemClass(className);
            System.out.println("        >>>>>> returning system class (in CLASSPATH).");
            return result;
        } catch (ClassNotFoundException e) {
            System.out.println("        >>>>>> Not a system class.");
        }

        /* Try to load it from our repository */
        classData = getClassImplFromDataBase(className);
        if (classData == null) {
            throw new ClassNotFoundException();
        }

        /* Define it (parse the class file) */
        result = defineClass(classData, 0, classData.length);
        if (result == null) {
            throw new ClassFormatError();
        }

        if (resolveIt) {
            resolveClass(result);
        }

        classes.put(className, result);
        System.out.println("        >>>>>> Returning newly loaded class.");
        return result;
    }
}


The code above is the first section of the loadClass method. As you can see, it takes a class name and searches a local hash table that our class loader is maintaining of classes it has already returned. It is important to keep this hash table around since you must return the same class object reference for the same class name every time you are asked for it. Otherwise the system will believe there are two different classes with the same name and will throw a ClassCastException whenever you assign an object reference between them. It's also important to keep a cache because the loadClass() method is called recursively when a class is being resolved, and you will need to return the cached result rather than chase it down for another copy. 

The next step is to check if the primordial class loader can resolve this class name. This check is essential to both the sanity and security of the system. For example, if you return your own instance of java.lang.Object to the caller, then this object will share no common superclass with any other object! The security of the system can be compromised if your class loader returned its own value of java.lang.SecurityManager, which did not have the same checks as the real one did.

After the initial checks, we come to the code above which is where the simple class loader gets an opportunity to load an implementation of this class. As you can see from the source code, the SimpleClassLoader has a method getClassImplFromDataBase() which in our simple example merely prefixes the directory "store\" to the class name and appends the extension ".impl". I chose this technique in the example so that there would be no question of the primordial class loader finding our class. Note that the sun.applet.AppletClassLoader prefixes the codebase URL from the HTML page where an applet lives to the name and then does an HTTP get request to fetch the bytecodes.

If the class implementation was loaded, the penultimate step is to call the defineClass() method from java.lang.ClassLoader, which can be considered the first step of class verification. This method is implemented in the Java virtual machine and is responsible for verifying that the class bytes are a legal Java class file. Internally, the defineClass method fills out a data structure that the JVM uses to hold classes. If the class data is malformed, this call will cause a ClassFormatError to be thrown. 

The last class loader-specific requirement is to call resolveClass() if the boolean parameter resolveIt was true. This method does two things: First, it causes any classes that are referenced by this class explicitly to be loaded and a prototype object for this class to be created; then, it invokes the verifier to do dynamic verification of the legitimacy of the bytecodes in this class. If verification fails, this method call will throw a LinkageError, the most common of which is a VerifyError.
Note that for any class you will load, the resolveIt variable will always be true. It is only when the system is recursively calling loadClass() that it may set this variable false because it knows the class it is asking for is already resolved.

The final step in the process is to store the class we've loaded and resolved into our hash table so that we can return it again if need be, and then to return the Class reference to the caller.
Of course if it were this simple there wouldn't be much more to talk about. In fact, there are two issues that class loader builders will have to deal with, security and talking to classes loaded by the custom class loader.

Class Loaders in Java



Today, I've read about class loaders. Sort of interesting. Similar to our inheritance heirachy and most of the stuff is working as we think how it could be.

The Class loader concept, one of the cornerstones of the Java virtual machine, describes the behavior of converting a named class into the bits responsible for implementing that class. Because class loaders exist, the Java run time does not need to know anything about files and file systems when running Java programs.

Class loaders are hierarchical. Classes are introduced into the JVM as they are referenced by name in a class that is already running in the JVM. So how is the very first class loaded? The very first class is specially loaded with the help of static main() method declared in your class. All the subsequently loaded classes are loaded by the classes, which are already loaded and running. A class loader creates a namespace. All JVMs include at least one class loader that is embedded within the JVM called the primordial (or bootstrap) class loader. It is somewhat special because the virtual machine assumes that it has access to a repository of trusted classes which can be run by the VM without verification.

When a new JVM instance is started , the bootstrap class loader is responsible for loading key java classes like java.lang.Object and other runtime code into memory. The runtime classes are packaged inside jre/lib/rt.jar file. We cannot find the details of the bootstrap class loader in the java language specification, since this is a native implementation. For this reason the behavior of the bootstrap class loader will differ across JVMs.

Java can change its class storage model simply by changing the set of functions that implements the class loader.

Now let’s look at non-primordial class loaders. The JVM has hooks in it to allow user defined class loaders to be used in place of primordial class loader.

ex : Bootstrap (primordial) Loads JDK internal classes, java.* packages. (as defined in the sun.boot.class.path system property, typically loads rt.jar and i18n.jar) and is the parent in the Class loaders hierarchy.

next comes the Extensions (Loads jar files from JDK extensions directory (as defined in the java.ext.dirs system property – usually lib/ext directory of the JRE) and then System (Loads classes from system classpath (as defined by the java.class.path property, which is set by the CLASSPATH environment variable or –classpath or –cp command line options) ClassLoaders.

Classes loaded by Bootstrap class loader have no visibility into classes loaded by its descendants (ie Extensions and Systems class loaders).

The classes loaded by system class loader have visibility into classes loaded by its parents (ie Extensions and Bootstrap class loaders).

If there were any sibling class loaders they cannot see classes loaded by each other. They can only see the classes loaded by their parent class loader. For example Sibling1 class loader cannot see classes loaded by
Sibling2 class loader

Both Sibling1 and Sibling2 class loaders have visibilty into classes loaded by their parent class loaders (eg: System, Extensions, and Bootstrap)


Class loaders are hierarchical and use a delegation model when loading a class. Class loaders request their parent to load the class first before attempting to load it themselves. When a class loader loads a class, the child class loaders in the hierarchy will never reload the class again. Hence uniqueness is maintained. Classes loaded by a child class loader have visibility into classes loaded by its parents up the hierarchy but the reverse is not true


Note : Two objects loaded by different class loaders are never equal even if they carry the same values, which mean a class is uniquely identified in the context of the associated class loader. This applies to singletons too, where each class loader will have its own singleton.

At its simplest, a class loader creates a flat name space of class bodies that are referenced by a string name. The method definition is:

Class r = loadClass(String className, boolean resolveIt);

The variable className contains a string that is understood by the class loader and is used to uniquely identify a class implementation. The variable resolveIt is a flag to tell the class loader that classes referenced by this class name should be resolved (that is, any referenced class should be loaded as well).

We can build our own ClassLoader by being a subclass of java.lang.ClassLoader. The only abstract method that must be implemented is loadClass().

Static Class Loading :

Classes are statically loaded with Java’s 'new' operator.

class MyClass {
 public static void main(String args[]) {
  Car c = new Car();
 }
}



A NoClassDefFoundException is thrown if a class is referenced with Java’s 'new' operator (i.e. static loading) but the runtime system cannot find the referenced class.

Dynamic class loading:

Dynamic loading is a technique for programmatically invoking the functions of a class loader at run time.

we can load classes dynamically by...

Class.forName (String className); //static method which returns a Class


The above static method returns the class object associated with the class name. The string className can be supplied dynamically at run time. Unlike the static loading, the dynamic loading will decide whether to load the class Car or the class Jeep at runtime based on a properties file and/or other runtime conditions. Once the class is dynamically loaded the following method returns an instance of the loaded class. It’s just like creating a class object with no arguments.


class.newInstance (); //A non-static method, which creates an instance of a class (i.e. creates an object).
Jeep myJeep = null ;

//myClassName should be read from a properties file or Constants interface.

//stay away from hard coding values in your program. 
String myClassName = "au.com.Jeep" ;
Class vehicleClass = Class.forName(myClassName) ;
myJeep = (Jeep) vehicleClass.newInstance();
myJeep.setFuelCapacity(50);


A ClassNotFoundException is thrown when an application tries to load in a class through its string name using the following methods but no definition for the class with the specified name could be found:
1. The forName(..) method in class - Class.
2. The findSystemClass(..) method in class - ClassLoader.
3. The loadClass(..) method in class - ClassLoader.

The Java virtual machine has hooks in it to allow a user-defined class loader to be used in place of the primordial one. Furthermore, since the user class loader gets first crack at the class name, the user is able to implement any number of interesting class repositories, not the least of which is HTTP servers -- which got Java off the ground in the first place.

There is a cost, however, because the class loader is so powerful (for example, it can replace java.lang.Object with its own version), Java classes like applets are not allowed to instantiate their own loaders. (This is enforced by the class loader, by the way.) This column will not be useful if you are trying to do this stuff with an applet, only with an application running from the trusted class repository (such as local files).


Java class loaders can be broadly classified into below categories:
  • Bootstrap Class Loader
    Bootstrap class loader loads java’s core classes like java.lang, java.util etc. These are classes that are part of java runtime environment. Bootstrap class loader is native implementation and so they may differ across different JVMs.
  • Extensions Class Loader
    JAVA_HOME/jre/lib/ext contains jar packages that are extensions of standard core java classes. Extensions class loader loads classes from this ext folder. Using the system environment propery java.ext.dirs you can add ‘ext’ folders and jar files to be loaded using extensions class loader.
  • System Class Loader
    Java classes that are available in the java classpath are loaded using System class loader.
You can see more class loaders like java.net.URLClassLoader, java.security.SecureClassLoader etc. Those are all extended from java.lang.ClassLoader