Skip to content

Latest commit

 

History

History
81 lines (59 loc) · 4.82 KB

File metadata and controls

81 lines (59 loc) · 4.82 KB
title Detailed Explanation of Class Loaders (Key Points)
category Java
tag
JVM

A Review of the Class Loading Process

Before introducing class loaders and the parent delegation model, let's briefly review the class loading process.

  • Class loading process: Loading -> Linking -> Initialization.
  • The linking process can be further divided into three steps: Verification -> Preparation -> Resolution.

Class Loading Process

Loading is the first step in the class loading process, mainly completing the following three tasks:

  1. Obtaining the binary byte stream that defines the class through its fully qualified name.
  2. Converting the static storage structure represented by the byte stream into a runtime data structure in the method area.
  3. Generating a Class object in memory that represents the class, serving as an access point for these data in the method area.

Class Loaders

Introduction to Class Loaders

Class loaders have been around since JDK 1.0, initially created to meet the needs of Java Applets (which have since been deprecated). Over time, they have become an important part of Java programs, enabling Java classes to be dynamically loaded into the JVM and executed.

According to the official API documentation:

A class loader is an object that is responsible for loading classes. The class ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to locate or generate data that constitutes a definition for the class. A typical strategy is to transform the name into a file name and then read a "class file" of that name from a file system.

Every Class object contains a reference to the ClassLoader that defined it.

Class objects for array classes are not created by class loaders, but are created automatically as required by the Java runtime. The class loader for an array class, as returned by Class.getClassLoader() is the same as the class loader for its element type; if the element type is a primitive type, then the array class has no class loader.

In summary, it means:

A class loader is an object responsible for loading classes. ClassLoader is an abstract class. Given the binary name of a class, a class loader should attempt to locate or generate data that constitutes a definition for the class. A typical strategy is to transform the name into a file name and then read a "class file" of that name from a file system.

Every Java class has a reference pointing to the ClassLoader that loaded it. However, array classes are not created by ClassLoader, but are automatically created by the JVM when needed. The ClassLoader for an array class, when obtained via getClassLoader(), is the same as that of its element type.

From the above introduction, we can see:

  • A class loader is an object responsible for loading classes, implementing the loading step in the class loading process.
  • Every Java class has a reference pointing to the ClassLoader that loaded it.
  • Array classes are not created by ClassLoader (array classes do not have corresponding binary byte streams) but are generated directly by the JVM.
class Class<T> {
  ...
  private final ClassLoader classLoader;
  @CallerSensitive
  public ClassLoader getClassLoader() {
     //...
  }
  ...
}

In simple terms, the main function of a class loader is to dynamically load the bytecode of Java classes (.class files) into the JVM (creating a Class object in memory that represents the class). The bytecode can be derived from Java source code (.java files) compiled by javac, or it can be dynamically generated by tools or downloaded over the network.

In addition to loading classes, class loaders can also load resources required by Java applications, such as text, images, configuration files, videos, and other file resources. This article will only discuss its core function: loading classes.

Class Loader Loading Rules

When the JVM starts, it does not load all classes at once but dynamically loads them as needed. This means that most classes are loaded only when they are actually used, which is more memory-friendly.

Classes that have already been loaded are stored in the ClassLoader. During class loading, the system first checks whether the current class has already been loaded. If it has, the loaded class is returned directly; otherwise, it attempts to load it. In other words, for a class loader, a class with the same binary name will only be loaded once.

public abstract class ClassLoader {
  ...
  private final ClassLoader parent;
  // Classes loaded by this class loader.
  private final Vector<Class<?>> classes = new Vector<>();
  // Called by VM to record each loaded class with this class loader.
  void addClass(Class<?> c) {
        classes.addElement(c);
   }