We will discuss the basics of Class Loading in Java.
Steps involved in Class Loading
Class loader loads, links, and initializes a class from a Java class file.
1. Loading: Loads the byte code into the method area of JVM from Java class file and creates an instance of java.lang.Class for that particular class.
2. Linking:It includes verification,preparation and resolution.
- Verification: checking that the class file is structurally well-formed and is fit for use by JVM.
- Preparation: involves the allocation of memory for class variables and sets them to default initial values. The class variables are not initialized to their proper initial values until the initialization phase.
- Resolution:Loads all the other classes referenced by a particular class.
3. Initialization: involves the process of initializing class variables.
The parent-delegation model
Any request for a class loader to load a given class is first delegated to its parent class loader before the requested class loader tries to load the class itself. The parent class loader, in turn, goes through the same process of asking its parent. This chain of delegation continues through to the bootstrap class loader. If a class loader’s parent can load a given class, it returns that class. Otherwise, the class loader attempts to load the class itself.
The JVM has three class loaders(Bootstrap,Extensions and Application), each possessing a different scope from which it can load classes.Apart from the JVM provided class loaders, you can also define custom class loaders.
As you descend the hierarchy, the scope of available class repositories widens, and typically the repositories are less trusted:
Bootstrap Class Loader
At the top of the hierarchy is the bootstrap class loader. This class loader is responsible for loading only the classes that are from the core Java™ API like java.lang, java.util etc. These are classes that are part of java runtime environment. These classes are the most trusted and are used to bootstrap the JVM.Bootstrap class loader is native implementation and so they may differ across different JVMs.
Extensions Class Loader
The extensions class loader can load classes that are standard extensions packages(JAVA_HOME/jre/lib/ext) in the extensions directory.
Application Class Loader
The application class loader can load classes from the local file system, and will load files from the CLASSPATH. The application class loader is the parent of any custom class loader or hierarchy of custom class loaders.
Because class loading is always delegated first to the parent of the class loading hierarchy, the most trusted repository (the core API) is checked first, followed by the standard extensions, then the local files that are on the class path. Finally, classes that are located in any repository that your own class loader can access, are accessible. This system prevents code from less-trusted sources from replacing trusted core API classes by assuming the same name as part of the core API.
Custom class loaders
You might want to write your own class loader so that you can load classes from an alternate repository, partition user code, or unload classes.
There are three main reasons why you might want to write your own class loader.
- To allow class loading from alternative repositories. This is the most common case, in which an application developer might want to load classes from other locations, for example, over a network connection.
- To partition user code. This case is less frequently used by application developers, but widely used in servlet engines.
- 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 dereferenced. For this reason, system and extension classes are never unloaded but application classes can be unloaded when their class loader is dereferenced.
Namespaces and the runtime package
Loaded classes are identified by both the class name and the class loader that loaded it. This separates loaded classes into namespaces that the class loader identifies.
A namespace is a set of class names that are loaded by a specific class loader. When an entry for a class has been added into a namespace, it is impossible to load another class of the same name into that namespace. Multiple copies of any given class can be loaded because a namespace is created for each class loader.
Namespaces cause classes to be segregated by class loader, thereby preventing less-trusted code loaded from the application or custom class loaders from interacting directly with more trusted classes. For example, the core API is loaded by the bootstrap class loader, unless a mechanism is specifically provided to allow them to interact. This prevents possibly malicious code from having guaranteed access to all the other classes.
You can grant special access privileges between classes that are in the same package by the use of package or protected access. This gives access rights between classes of the same package, but only if they were loaded by the same class loader. This stops code from an untrusted source trying to insert a class into a trusted package. As discussed earlier, the delegation model prevents the possibility of replacing a trusted class with a class of the same name from an untrusted source. The use of namespaces prevents the possibility of using the special access privileges that are given to classes of the same package to insert code into a trusted package.