Class Loading in J2SE Environment

Java Class Loading mechanism is one of the darkest corners inside java virtual machine. The class loading concept describes the behavior of converting a named class into the bits responsible for implementing that class.

Wait a minute! “I never have to deal with it. Why do I need to know this bulky philosophy”, this might flash in your mind. In that case, think of below-

ClassNotFoundException

NoClassDefFoundError

ClassCastException

Sounds familiar?

Most of the developers have had this frustrating experience trying to debug some of these exceptions. Post Java2, class loading is no longer as simple as defining a CLASSPATH environment variable. J2EE application servers supplement the CLASSPATH with many different mechanisms. The Java ClassLoader is a crucial, but often overlooked, component of the Java run-time system.

Okay, so what really a ClassLoader is?

Let’s start with the basics. A Java program, isn’t a single executable file, but is composed of many individual class files containing the platform-independent byte code. During execution, classes are not loaded into JVM memory all at once, but based on demand, as needed by the program – this is where the ClassLoaders come into picture. A classloader is a subclass of the java.lang.ClassLoader class. Each classloader, in turn, is designed to work with one or more codesources. A codesource is a root location from which the JVM searches for classes. Codesources can be defined to represent physical storage of binary class files, URLs, or even classes generated on the fly.

What is Class Loading?

The term “class loading” refers to the process of locating the bytes for a given class name and converting them into a Java Class instance. All java.lang.Class instances within a JVM start life as an array of bytes, structured in the class file format defined by the JVM specification.

Class loading in J2SE environment

When a JVM is started (in all versions since JDK 1.2), it forms an initial classloader hierarchy composed of three loaders:

  • The bootstrap (also known as “primordial”) loader is responsible for loading the core Java classes (rt.jar & i18n.jar). This “loader” is unique in that it is not actually a subclass of java.lang.ClassLoader but is implemented by the JVM itself.
  • The class loader delegation model The extension loads classes from the jars in the JRE’s extension directory (jre/lib/ext). This provides a standard mechanism to introduce new functionality beyond the core Java classes. Calling getParent() on this instance will always return null, since the bootstrap loader is not an actual ClassLoader instance.
  • The system loader is responsible for loading classes from the directories and jars listed on the command-line (-cp/-classpath) and/or the java.class.path and CLASSPATH system properties. If not otherwise specified, any user instantiated ClassLoader will have this loader as its parent.
  • The user defined ClassLoader allows applications to customize class loading as per their needs

Phases of Class Loading

The entire class loading process can essentially be broken down into three phases-

  • Loading
    • Locating the required class file and loading the bytecode
    • Gives a very basic memory structure to the class object. Methods, fields, and other referenced classes. A notable point here is that the referenced classes are not dealt with at this stage therefore, the class is not usable
  • Linking
    • Bytecode verification – The class loader does a number of checks on the bytecodes
    • Class preparation – Prepares the necessary data structures that represent fields, methods, and implemented interfaces that are defined within classes
    • Resolving – Loads all the other referenced classes (Superclasses, Interface, Fields, Method signature, Local variables)
  • Initialization – any static initializes contained within a class are executed

The phases of class loading

Three Principles of ClassLoader Operation

  • Delegation Principal
    • According to this principle, if a particular class is not loaded already, the classloaders delegate the requests to load that class to their parent classloaders.
    • Since the System-Classpath classloader loaded the MyApp class, it first asks its parent, the extension classloader to load the class. The extension classloader asks the Bootstrap classloader to load java.util.Vector. Since java.util.Vector is a J2SE class, the bootstrap classloader loads it and returns.

image

    • In case MyApp creates new instance of MyClass, bootstrap & extension classloaders cannot find the class. Finally the request comes back to system classloader which finds the class and loads it.

image

  • Visibility Principal
    • According to this principle, Classes loaded by parent classloaders are visible to child classloaders but not vice versa
    • For classes loaded by ClassLoader X, classes A, B and X are visible, but not class Y. Sibling classloaders cannot see each other’s classes.

  • Uniqueness Principal
    • According to this principle, when a classloader loads a class, the child classloaders in the hierarchy will never reload the class. This follows from the delegation principle since a classloader always delegates class loading to its parents. The child classloader will load it (or try to load it) only if the parent hierarchy fails to load the class. Thus the uniqueness of the class is maintained. An interesting scenario emerges when both parent and child classloaders load the same

image

ClassLoader Namespaces

  • Each classloader (or instance of a ClassLoader subclass) defines a unique and separate namespace.
  • For a given class with name N, only one instance of class N may exist within a given classloader. But the same class can be loaded by two different classloaders
  • JVM considers each class to be further qualified by the ClassLoader instance that loaded it. In effect, the full name of a class consists of its fully qualified class name plus its classloader
  • If two different classloaders load com.test.cl.vo.B, there will be two Class instances, each with its own separate static data. Any attempt to cast an object from one to the other will result in a ClassCastException
  • So, your singleton is per classloader hierarchy than the JVM

How to access a ClassLoader

  • class.getClassLoader()
  • classLoader.getSystemClassLoader()
  • Thread.currentThread().getContextClassLoader()
  • An application specific method to retrieve a classloader

In all the cases initial loader selection is critical because it defines the visibility.

Explicit v/s Implicit Class Loading

  • Explicit class loading occurs when class is loaded using one of the following method
    • cl.loadClass() – where cl is an instance of java.lang.ClassLoader)
    • Class.forName() – the starting class loader is the defining class loader of the current class

If the Class whose name is specified is already loaded, classloader returns the reference to it from cache. Otherwise loader goes through the delegation model to load the class.

  • Implicit class loading occurs when the class is loaded as a result of reference, inheritance or initialization. Again, class is either returned from cache or through the delegation model.

Classes are often loaded through a combination of explicit and implicit class loading. For example, a class loader could first load a class explicitly and then load all of its referenced classes implicitly.

Why to write a custom class loader?

Following are some of the catalysts-

  • To allow class loading from alternative repositories – Load classes that are not in the classpath – over the network, out of a database, from Java source code, out of a plug-in directory, or generate them on the fly
  • Selectively load a specific version – All application developers to check for update and selectively load classes from specific locations (jar/zip/folder).
  • To allow the unloading of classes – This case is useful if the application creates large numbers of classes that are used for only a finite period. Because a class loader maintains a cache of the classes that it has loaded, these classes cannot be unloaded until the class loader itself has been de-referenced. For this reason, system and extension classes are never unloaded, but application classes can be unloaded when their classloader is.
  • Security – Your ClassLoader could examine classes before they are handed off to the JVM to see if they have a proper digital signature.
  • Encryption – It’s possible to create a ClassLoader that decrypts on the fly, so that your class files on disk are not readable by someone with a decompiler.
  • Archiving – Want to distribute your code in a special format or with special compression? Your ClassLoader can pull raw class file bytes from any source it wants.

Common Class Loading Issues

  • ClassNotFoundException
    • Thrown when an application tries to explicitly load a class using class name string and class (.class file) is not found in the classpath
    • Can be easily checked by enabling verbose:class JVM argument

  • NoClassDefFoundError
    • Thrown if the ClassLoader instance tries to implicitly load in the definition of a class and no definition of the class could be found.

  • ClassCastException
    • Thrown as a result of incompatible types being found in a type comparison. It indicates that the code has attempted to cast an object to a subclass of which it is not an instance. (remember ClassLoader Namespace)
    • Two classes of the same fully qualified name are not equal to each other if they are loaded by different ClassLoaders. They cannot be cast to each other and such operations would result in a ClassCastException

Class Loading Options

Following Table summarizes the command-line options for setting the classpaths of the three standard class loaders:

Command-line option

Explanation

Class loader involved

-Xbootclasspath:<directories and zip/JAR files separated by ; or :

Sets the search path for bootstrap classes and resources.

Bootstrap

-Xbootclasspath/a:<directories and zip/JAR files separated by ; or :

Appends the path to end of the boot classpath.

Bootstrap

-Xbootclasspath/p:<directories and zip/JAR files separated by ; or :

Prefix the path to front of the boot classpath.

Bootstrap

-Djava.ext.dirs=<directories and zip/JAR files separated by ; or :

Specifies the search path for the extension classes and resources.

Extension

-cp or -classpath <directories and zip/JAR files separated by ; or :

Sets the search path for application classes and resources.

System

-Djava.class.path=<directories and zip/JAR files separated by ; or :

Sets the search path for application classes and resources.

System

Author – Yogendra sharma (YES)