1. Life cycle of class loading
2. What is class loading
After compiling a.java file into a.Class bytecode file through javac, the process by which the loader loads the bytecode file into the JVM is called class loading:
- Gets the binary byte stream that defines this class by its full class name;
- Converts the static storage structure represented by the byte stream to the runtime data structure of the method area;
- Generates a Class object in memory that represents this class as an access entry to the data in the method area.
3. Three-tier Class Loader
- Bootstrap ClassLoader: Part of the virtual machine, implemented in C++, loads <JAVA_ Class libraries stored in the HOME>/jre/lib directory or in the path specified by the -Xbootclasspath parameter.
- Extension Class Loader: Load <JAVA_using a Java implementation independent of the virtual machine All class libraries in the HOME>/jre/lib/ext directory or in the path specified by the java.ext.dirs system variable.
- Application ClassLoader: Loads all the class libraries of the CLASSPATH directory of the application using a Java implementation, independent of the virtual machine. (
import sun.misc.Launcher; import java.net.URL; /** * Creator: zjm * Creation time: 2022/8/24 * Description: * Start the class loader (Bootstrap ClassLoader), * Extension Class Loader, * Directory loaded by Application Class Loader */ public class JDKClassLoader { public static void main(String[] args) { System.out.println("bootstrapLoader Load the following file:"); URL[] urls = Launcher.getBootstrapClassPath().getURLs(); for (URL url : urls) { System.out.println(url); } System.out.println("ExtClassLoader Load the following files:"); System.out.println(System.getProperty("java.ext.dirs")); System.out.println("AppClassLoader Load the following files:"); System.out.println(System.getProperty("java.class.path")); } }
Output:
BootstrapLoader Load the following file: file:/D:/Program%20Files/Java/jdk1.8.0_181/jre/lib/resources.jar file:/D:/Program%20Files/Java/jdk1.8.0_181/jre/lib/rt.jar file:/D:/Program%20Files/Java/jdk1.8.0_181/jre/lib/sunrsasign.jar file:/D:/Program%20Files/Java/jdk1.8.0_181/jre/lib/jsse.jar file:/D:/Program%20Files/Java/jdk1.8.0_181/jre/lib/jce.jar file:/D:/Program%20Files/Java/jdk1.8.0_181/jre/lib/charsets.jar file:/D:/Program%20Files/Java/jdk1.8.0_181/jre/lib/jfr.jar file:/D:/Program%20Files/Java/jdk1.8.0_181/jre/classes ExtClassLoader Load the following files: D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext; C:\Windows\Sun\Java\lib\ext AppClassLoader Load the following files: D:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar; D:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar; D:\ideaWorkSpace\out\production\jvmDemo; D:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4\lib\idea_rt.jar Process ended, exit code 0
4. Class loading core source (how parental delegation works):
When a class loader receives a load request, it does not directly load the specified class, but delegates the request to its parent loader to load (instead of inheriting from each loader, it uses the parent parameter to determine the parent-to-parent relationship), that is, all load requests are ultimately delegated to the top-level loader (Bootstrap ClassLoader) to try to load the class, only if the parent class cannot be loaded. Only subclasses attempt to load and throw exceptions if none can be loaded.
Parental Delegation Mechanism Implementation Source:
The subclass does not do the loading, it just delegates up: return super.loadClass(var1, var2);
public Class<?> loadClass(String var1, boolean var2) throws ClassNotFoundException { int var3 = var1.lastIndexOf(46); if (var3 != -1) { SecurityManager var4 = System.getSecurityManager(); if (var4 != null) { var4.checkPackageAccess(var1.substring(0, var3)); } } if (this.ucp.knownToNotExist(var1)) { Class var5 = this.findLoadedClass(var1); if (var5 != null) { if (var2) { this.resolveClass(var5); } return var5; } else { throw new ClassNotFoundException(var1); } } else { return super.loadClass(var1, var2); } }
//super.loadClass(var1, var2) protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{ synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
Parental Delegation Mechanism Diagram:
5. Why use parental delegation mechanism
Security: Even if you define a Java.lang.String yourself, the loader will pass
AppClassLoader--->ExtClassLoader-->BootstrapLoader path loaded into core jar package. It prevents the core API libraries from being tampered with arbitrarily.
Avoid class duplication: When the father has already loaded the class, the child ClassLoader will not be loaded.
Give an example:
6. How to break the parental delegation mechanism:
The parental delegation mechanism is implemented by the loadClass method in the java.lang.ClassLoader class. As long as you customize the class loader and override the loadClass method, tomcat breaks the parental delegation mechanism.