digitization, transformation, binary

Class ClassLoader in Java

Class ClassLoader in Java

ClassLoader is an abstract class. The applications implement subclasses of Classloader to extend the mechanism by which JVM dynamically loads classes.

The class loader loads the class files from the code and Java API’s library. (The necessary class files those are needed to execute the program are loaded.) Then the whole set of byte codes are executed into an execution engine.

The execution engine is one of the integral parts of the virtual machine which has several implementations. The simple and straightforward implementation sequentially interprets the byte codes.

The complex one is the just in time compiler. In this implementation byte codes of a method are compiled to native machine code has the first occurrence of the method invocation. The native machine code, then cached for reusability.

The third type of implementation is called Adaptive Optimizer. In this implementation, the virtual machine starts interpreting byte codes, but actively monitor the activities. The monitor process keeps noting down the heavily used area of the code. As an optimization process, the virtual machine compiles to native machine code and keep optimizing the heavily used area of the code.

The remaining area of the code .which is used but not that heavily remains as byte codes, which the virtual machine keeps on interpreting. Majorly it uses a Pareto principle (80-20 rule) to identify the heavily need an area of the code. This 20 % of the code falls under performance improvement.

Finally, the JVM built on top of a chip that executes the java byte codes natively. The execution engine is embedded in the chip. When the JVM runs on top of an operating system, a Java program talks to the operating system by invoking native methods.

In Java there are two types of methods:-

  • Java’s internal methods
  • Native methods.

Java’s internal methods are written in the Java language. They are compiled to byte codes. They are saved in separate class files. A native method is written on some other languages(C, C++ etc.)

They are compiled to the native machine codes for a specific processor. Native Methods are stored in DLL (dynamic link library files). While the java methods are platform dependant native Methods are platform-specific.

When running a  java program, it intern calls the native methods. The virtual machine then loads the corresponding DLL file that contains the specific and corresponding method. Once involved, Java executes the method.

Native Methods can provide Java direct access to the resources of the beneath operating system. Now Native methods will render our code to a controlled platform-specific environment as they are all platform dependant. They may also render our code to a particular implementation of the  Java platform.

The Java Native Interface(JNI) enables native methods to execute on a computer for any Java platform. There may be chances where we want to access resources of any particular host and that may be unavailable. In that case, we need to write our API’s to call native Methods to make our code system independent.

The ClassLoader Architecture

The class loader architecture acts as a safeguard for Java’s security and helps in network mobility. Inside the Java virtual machine, there can be more than one class loader. The JVM (Java Virtual Machine) has a set of flexible and custom class loaders that allows classes to load in customized ways.

A Typical Java application can utilize two different types of class loaders.

They are as follows-

  • Bootstrap class loader
  • User-defined class loader.

Bootstrap ClassLoader

The bootstrap class loader is a part of the Java Virtual Machine implementation. It is often referred to as primordial class loader or the system class loader or default class loader.  For example, if a Java Virtual Machine is Implemented as a c++ program on top of an existing operating system, the bootstrap Classloader will be part of the c++ coding. The Bootstrap class loader loads classes from Java API’s and local drives.

During execution, a Java application can install user-defined class loaders which load classes in the different customized way ( like download a class from network and load). Extract from the database, or build them on the fly.

User-Defined ClassLoader

User-defined class loaders are not an intrinsic part of the Java Virtual Machine. The user-defined class loaders are always a virtual machine. They are instantiated like normal class viz objects.

Because of the user-defined class loaders, we do not need to know all the classes that may ultimately help in running our application during compile time. They enable us to dynamically extend a Java application at runtime. During execution, Java can figure out the extra classes that need to be loaded .

Once Java figures out the list of classes, Java Virtual Machine, with the help of user-defined class loaders, load them one by one.

READ  Identifier and Keyword Concept Simplified In Java
A part of JVM implementation
A part of JVM implementation

During the class loading process Java, Virtual Machine keeps track of the class loader. ( User-defined or bootstrap ) and the class loader. If a loaded class refers to another class, the virtual machine checks the class loader from its track record and request’s the same class loader to load the referenced class.

Example, if the user defined loader loads a class ‘shape’ and that shape class now has a reference to’ Triangle’ class, The JVM ( Java Virtual Machine) will request the same user-defined class loader to load Triangle class. This phenomenon enables us to create multiple name-spaces inside a single Java application.

Now a Java application can instantiate multiple user-defined class loaders. They can reside in the same class or different classes. Hence the application may create multiple numbers of class loaders.

Interestingly classes loaded by different class loaders are in different namespaces. They cannot access others until and unless the application explicitly permits this access operation. So when we write our Java application code, we can very well segregate classes loaded from different sources into different namespaces.

The class loader architecture helps to control the interaction between code loaded from different sources. This also prevents any hostile code from gaining access to any of the resources.

By enabling us to instantiate user-defined class loaders that know how to download class files from networks, Java’s class loader architecture thus support network mobility. Java also supports security by enabling us to load class files from different sources through different user-defined class loaders. Lastly, the class files from sources are put in the different namespace that restricts access between codes.

ClassLoader Working Principle

In general JVM loads classes from the local file system in a platform-dependent manner(directory defined by CLASSPATH), however, some classes may be originated from another source like network or by an application.

The ClassLoader class provides a mechanism for Java to load classes over a network or from any source other than the local filesystem. The default class-loading mechanism loads classes from files found relative to directories specified by the CLASSPATH environment variable. This default mechanism does not use an instance of the ClassLoader class.

Three pillars of Java
Three pillars of Java

An application can implement another mechanism for loading classes by declaring a subclass of the abstract ClassLoader class. A subclass of ClassLoader must override the loadClass() to define a class-loading policy.

This method implements any sort of security that is necessary for the class-loading mechanism. The other methods of ClassLoader are final, so they cannot be overridden.

A ClassLoader object is typically used by calling its loadClass() method to explicitly load a top-level class, such as a subclass of Applet. The ClassLoader that loads the class becomes associated with the class; it can be obtained by calling the getClassLoader() method of the Class object that represents the class.

VirtualMachine primary task
VirtualMachine primary task

Once a class is loaded, it must be resolved before it can be used. Resolving a class means ensuring that all of the other classes it references are loaded. Besides, all of the classes that they reference must be loaded, and so on, until all of the needed classes have been loaded. Classes are resolved using the resolveClass() method of the ClassLoader object that
loaded the initial class. This means that when a ClassLoader object is explicitly used to load a class, the same ClassLoader is used to load all of the classes that it references, directly or indirectly.

Classes loaded using a ClassLoader object may attempt to load additional classes without explicitly using a ClassLoader object. They can do this by calling the Class class’ forName() method. However, in such a situation, a ClassLoader object is implicitly used. See the description of Class.forName() for more information.

How Virtual machine works
How Virtual machine works

Java identifies a class by a combination of its fully qualified name and the class loader that was used to load the class. If you write a subclass of ClassLoader, it should not attempt to directly load local classes. Instead, it should call findSystemClass().

A local class that is loaded directly by a ClassLoader is considered to be a different class than the same class loaded by findSystemClass(). This can lead to having two copies of the same class loaded, which can cause several inconsistencies. For example, the class’ equals() method may decide that the same object is not equal to itself.

In short, this class defines the necessary hook for Java to load classes over the network, or from other sources. Normal applications do not need to use or subclass this class.

The method defineClass() converts an array of bytes into an instance of a class. Instances of this newly created /defined class can be created by using the newInstance() method of the class-Class. The methods and constructors of objects created by a ClassLoader may reference other classes.

To determine the class(es) referred to, the JVM calls the loadClass() method of the ClassLoader that created the class. If JVM only needs to determine if the class exists or if it does not exists, to know its superclass, the resolve flag is set to false. However if an instance of the class is being created or any of its methods are being called, the class must also be resolved.

READ  EventObject Class in Java

In this case, the flag resolve is set to true and the resolveClass() method is called.

The structure of the ClassLoader class is given below:

public abstract class java.lang.ClassLoader extends java.lang.Object{
//constructor
protected ClassLoader();//creates a new classloader and initializes it. if there is a security manager, it check by createClassLoader() method.It may result in a SecuryException if the current thread does not have permission to create a new ClassLoader.
//Methods:
// Protected Constructor
protected ClassLoader();
// Class Methods
public static final URL getSystemResource(String name);
public static final InputStream getSystemResourceAsStream(String name);
// Public Instance Methods
public URL getResource(String name);
public InputStream getResourceAsStream(String name);
public Class loadClass(String name) throws ClassNotFoundException;
// Protected Instance Methods
protected final Class defineClass(byte[] data, int offset, int length);
protected final Class defineClass(String name, byte[] data, int offset,int length);
protected final Class findLoadedClass(String name);
protected final Class findSystemClass(String name) throws ClassNotFoundException;
protected abstract Class loadClass(String name, boolean resolve) throws ClassNotFoundException;
protected final void resolveClass(Class c);
protected final void setSigners(Class cl, Object[] signers);
} 

The details of the class structure are given as follows:

protected ClassLoader();

protected ClassLoader() constructor initializes a ClassLoader object. Because ClassLoader is an abstract class, only subclasses of the class can access this constructor.

public static final URL getSystemResource(String name);

public static final URL getSystemResource(String name) method finds a system resource with the given name and returns a URL object that is connected to the resource. The resource name can be any system resource.

This method returns a URL object that is connected to the specified system resource or null if the resource cannot be found.

Parameter
name – A system resource name.

public static final InputStream getSystemResourceAsStream(String name);

public static final InputStream getSystemResourceAsStream(String name) method finds a system resource with the given name and returns an InputStream object that is connected to the resource. The resource name can be any system resource.

This method returns an InputStream object that is connected to the specified system resource or null if the resource cannot be found.

Parameter
name – A system resource name.

public URL getResource(String name);

public URL getResource(String name) method finds a resource with the given name and returns a URL object that is connected to the resource.

A resource is a file that contains data (e.g., sound, images, text) and it can be part of a package. The name of a resource is a sequence of identifiers separated by “/”. For example, a resource might have the name test/mypackage/applogon.html.

System resources are found on the host machine using the conventions of the host implementation. For example, the “/” in the resource name may be treated as a path separator, with the entire resource name treated as a relative path to be found under a directory in CLASSPATH.

The implementation of getResource() in ClassLoader simply returns null. A subclass can override this method to provide more useful functionality.

This method returns a URL object that is connected to the specified resource or null if the resource cannot be found.
Parameter
name – A system resource name.

public InputStream getResourceAsStream(String name);

public InputStream getResourceAsStream(String name) method finds a resource with the given name and returns an InputStream object that is connected to the resource.

A resource is a file that contains data (e.g., sound, images, text) and it can be part of a package. The name of a resource is a sequence of identifiers separated by ‘/’. For example, a resource might have the name test/mypackage/applogon.html.

System resources are found on the host machine using the conventions of the host implementation. For example, the ‘/’ in the resource name may be treated as a path separator, with the entire resource name treated as a relative path to be found under a directory in CLASSPATH.

The implementation of getResourceAsStream() in ClassLoader simply returns null. A subclass can override this method to provide more useful functionality.

This method returns an InputStream object that is connected to the specified resource or null if the resource cannot be found.
Parameter
name – A system resource name.

public Class loadClass(String name);

public Class loadClass(String name) method loads the named class by calling loadClass(name, true).

This method returns the Class object for the specified class.
Parameter
name – The name of the class to be returned. The class name should be qualified by its package name. The lack of an explicit package name specifies that the class is part of the default package.

protected final Class defineClass(byte[] data, int offset, int length);

protected final Class defineClass(byte[] data, int offset, int length) method creates a Class object from the byte codes that define the class. Before the class can be used, it must be resolved. The method is intended to be called from an implementation of the loadClass() method.
Note that this method is deprecated as of Java 1.1. We need to use the version of defineClass() that takes a name parameter and is, therefore, more secure.

READ  Abstract interface ObjectInputValidation in Java

This method returns the newly created Class object.
Parameter
data – An array that contains the byte codes that define a class.
offset – The offset in the array of byte codes.
length – The number of byte codes in the array.

protected final Class defineClass(String name, byte[] data, int offset,int length);

protected final Class defineClass(String name, byte[] data, int offset, int length) method creates a Class object from the byte codes that define the class. Before the class can be used, it must be resolved. The method is intended to be called from an implementation of the loadClass() method.

This method returns the newly created Class object.
Parameter
name – The expected name of the class to be defined or null if it is not known. The class name should be qualified by its package name. The lack of an explicit package name specifies that the class is part of the default package.
data – An array that contains the byte codes that define a class.
offset – The offset in the array of byte codes.
length -The number of byte codes in the array.

protected final Class findLoadedClass(String name);

protected final Class findLoadedClass(String name) method finds the specified class that has already been loaded.
This method returns the Class object for the specified loaded class or null if the class cannot be found.
Parameter
name – The name of the class to be returned. The class name should be qualified by its package name. The lack of an explicit package name specifies that the class is part of the default package.

protected final Class findSystemClass(String name) throws ClassNotFoundException;

protected final Class findSystemClass(String name) throws ClassNotFoundException method finds and loads a system class if it has not already been loaded. A system class is a class that is loaded by the default class-loading mechanism from the local filesystem. An implementation of the loadClass() method typically calls this method to attempt to load a class from the locations specified by the CLASSPATH environment variable.

This method returns the Class object for the specified system class.
Parameter
name – The name of the class to be returned. The class name should be qualified by its package name. The lack of an explicit package name specifies that the class is part of the default package.

protected abstract Class loadClass(String name, boolean resolve) throws ClassNotFoundException;

protected abstract Class loadClass(String name, boolean resolve) abstract method loads the named class and returns its Class object. It is permitted and encouraged for an implementation to cache the classes it loads, rather than load one each time the method is called. An implementation of this method should do at least the following:

  • Load the byte codes that comprise the class definition into a byte[].
  • Call the defineClass() method to create a Class object to represent the class definition.
  • If the resolve parameter is true, call the resolveClass() method to resolve the class.

If an implementation of this method caches the classes that it loads, it is recommended that it use an instance of the java.util.Hashtable to implement the cache.

This method returns the Class object for the specified class.
Parameter
name – The name of the class to be returned. The class name should be qualified by its package name. The lack of an explicit package name specifies that the class is part of the default package.
resolve – Specifies whether or not the class should be resolved by calling the resolveClass() method.

protected final void resolveClass(Class c);

protected final void resolveClass(Class c) method resolves the given Class object. Resolving a class means ensuring that all of the other classes that the Class object references are loaded. Besides, all of the classes that they reference must be loaded, and so on, until all of the needed classes have been loaded.

The resolveClass() method should be called by an implementation of the loadClass() method when the value of the loadClass() method’s resolve parameter is true.

Parameter
c – The Class object for the class to be resolved.

protected final void setSigners(Class cl, Object[] signers);

protected final void designers(Class cl, Object[] signers) method specifies the objects that represent the digital signatures for this class.
Parameter
cl – The Class object for the class to be signed.
signers – An array of Objects that represents the signers of this class.

Apart from these ClassLoader class also has inherited methods from class- Object. They are as follows:

  • clone()
  • finalize()
  • hashCode()
  • notifyAll()
  • wait()
  • wait(long, int)
  • equals(Object)
  • getClass()
  • notify()
  • toString()
  • wait(long)

Share and Enjoy !

Leave a Comment

Your email address will not be published. Required fields are marked *