Sharing is the transmission of value, like a like

The introduction

Hello, if you are a programmer engaged in Java industry, whether you are white or old driver, I believe this article will bring you

Different degrees of receiving goods can not say that you read my article from now on master JVM play all over the world without rivals, but I can guarantee that read my article and practice to understand, at least in the JVM

More than 80 percent of programmers are crushed in this field. So without further ado let’s get down to business. (This article is serialized, please continue to pay attention!!)

One: class loading

I’m sure many of you who are working in Java have read a lot of articles and tutorials about the JVM on the Internet or in videos, but there is something missing. So let me tell you why

It feels that way because a lot of people or a lot of articles about JVMS are not dissecting them from the bottom up, from the habitual human mind. Starting today, I’m going to take that little bit of the JVM

Let’s get this straight for the boys. You are guaranteed to see another wonderful world in the JVM world.

Let’s cut to the chase. Before we talk about class loaders, let’s start with class loading. How does Java base load a class, and in what order? The following

I’ll walk you through it hand by hand.

In Java code, type loading, concatenation, and initialization are all done at runtime.

Type loading: What do we mean by type?

A: Type refers to our Java source code through a compiled class file

What are the sources of ** types? ** type of sources I summarized the following seven points

A:

1: indicates a local disk

2: Download. Class files from the network

3: war, jar to load the. Class file

4: Reading.class files from a dedicated database (rare)

5: Dynamically compile Java source files into class files

Typical is dynamic proxy, which generates class files at runtime

7: Our JSP will be converted into servlets, and our Serlvet is a Java file that will be compiled into a class file

So how does ours load? How is it loaded into the JVM?

A: Load through our classLoader

First let’s look at the following class loaders. The system-level class loaders are as follows

1: Start the Bootstrap Classloader

2: Extention ClassLoader

3: Application class loader

Non-system level classloaders are as follows:

1: Custom class loaders

Let’s take a look at class loaders one by one, talk about their past and present lives, and what they do, to give you a thorough understanding of what class loaders really are.

Bootstrap Classloader (Bootstrap Classloader

Load responsibilities: Load JAVA_HOME/jre/lib/rt.jar. The loader is implemented in C++, not a subclass of the ClassLoader class.

We’ll show you what a classloader is in a code interlude. A lot of people just use their mouth, so they can understand at the time, but they can’t

Get a real taste of class loaders and the essence of class loading. This is only the right way to learn if you can verify your claims with examples. Let’s cut to the chase.

Class MainClass01 (SRC /com.test) : 1.8.0_144 SRC /com.test

Let’s start by looking at what packages our startup class loader actually loads in code

package com.test;

import java.util.Arrays;
import java.util.List;

/** * JVM class loader chapter 1 *@authorGeektime - time * Prints the path to start the classloader loading */
public class MainClass01 {
    
    public static void main(String[] args) {

        String bootStrapLoadingPath = System.getProperty("sun.boot.class.path");
        List<String> bootLoadingPathList = Arrays.asList(bootStrapLoadingPath.split(";"));
        for(String bootPath:bootLoadingPathList) {
            System.out.println("Start class loader loading directory :{}"+bootPath); }}}"C: \ Program Files \ Java \ jdk1.8.0 _144 \ bin \ Java exe" "-JavaAgent :C: Program Files\JetBrains\IntelliJ IDEA 2019.2\lib\idea_rt.jar=60329:C: Program Files\JetBrains\IntelliJ The IDEA of 2019.2 \ bin" -Dfile.encoding=UTF-8 -classpath "C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ charsets jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ deploy the jar. C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ access - bridge - 64. The jar. C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ cldrdata jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ DNSNS jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ jaccess jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ JFXRT jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ localedata jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ nashorn jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunec jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunjce_provider jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunmscapi jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunpkcs11 jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ zipfs jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ javaws jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ jce jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ JFR jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ JFXSWT jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ jsse jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ management - agent jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ plugin jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ resources jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ rt jar; I:\jvm\out\production\jvm-classloader"Com.test. MainClass01 starts the class loader loading directory :{}C: Program Files\Java\jdk18.. 0 _144\jre\lib\resources.jar Starts the class loader loading directory :{}C: Program Files\Java\jdk18.. 0 _144\jre\lib\rt.jar Starts the class loader loading directory :{}C: Program Files\Java\jdk18.. 0 _144\jre\lib\sunrsasign. Jar Starts the class loader loading directory :{}C: Program Files\Java\jdk18.. 0 _144\jre\lib\jsse.jar Starts the class loader loading directory :{}C: Program Files\Java\jdk18.. 0 _144\jre\lib\jce.jar Starts the class loader loading directory :{}C: Program Files\Java\jdk18.. 0 _144\jre\lib\charsets.jar Starts the class loader loading directory :{}C:\Program Files\Java\jdk18.. 0 _144\jre\lib\jfr.jar Starts the class loader loading directory :{}C: Program Files\Java\jdk18.. 0 _144\jre\classes

Process finished with exit code 0


Copy the code

As you can see from running the code above, the class loader is launched to load the following JAR packages. It contains what is commonly known as RT.jar. C:\Program Files\Java\jdk1.8.0_144\jre\classes So if we write a Class, compile it into a Class file and throw it into this directory will it get loaded? Let’s give it a try. We create a Cat class under the com.test package. Then find the compiled cat. class file and throw it into C: Program Files Java jdk1.8.0_144 jre classes.

As you can see, our JRE directory does not have classes, so we create one manually and throw the cat.class file into it. We then get what cat. classLoader is in the test class to see if Cat is loaded by the startup classLoader.

From the above results, we can see that our Cat class is indeed loaded by the launcher class loader. Why null? When a class is loaded by the launcher class loader, its getClassLoader returns null, which is the difference between the launcher class loader and other classloaders.

Supplementary notes: Bootstrap Classloader is loaded by C++, and then the Bootstrap Classloader loads rt jar packages. The Bootstrap Classloader also loads the system class loader and the extension class loader, both of which are located at sun.boot.class.path.

Two: Extention ClassLoader focus analysis

Load responsibility: Load jar package of Java platform extension, \lib\ext, can be specified with -djava.ext.dirs load path

The loader is written in Java code and is a subclass of ClassLoader, located in Sun.misc.Launcher$ExtClassLoader, an inner class of our Launch class

Again, let’s test it in MainClass01

package com.test;

import java.util.Arrays;
import java.util.List;

/** * JVM class loader chapter 1 *@authorGeek time-time * Prints the directory loaded by the boot class loader * prints the directory loaded by the extension class loader */
public class MainClass01 {

    public static void main(String[] args) {

        String extLoadingPath = System.getProperty("java.ext.dirs");
        List<String> list = Arrays.asList(extLoadingPath.split(";"));
        for(String extpath:list) {
            System.out.println("Extension class loader loading directory :{}"+extpath); }}}"C: \ Program Files \ Java \ jdk1.8.0 _144 \ bin \ Java exe" "-JavaAgent :C: Program Files\JetBrains\IntelliJ IDEA 2019.2\lib\idea_rt.jar=59761:C: Program Files\JetBrains\IntelliJ The IDEA of 2019.2 \ bin" -Dfile.encoding=UTF-8 -classpath "C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ charsets jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ deploy the jar. C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ access - bridge - 64. The jar. C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ cldrdata jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ DNSNS jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ jaccess jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ JFXRT jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ localedata jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ nashorn jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunec jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunjce_provider jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunmscapi jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunpkcs11 jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ zipfs jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ javaws jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ jce jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ JFR jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ JFXSWT jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ jsse jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ management - agent jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ plugin jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ resources jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ rt jar; I:\jvm\out\production\jvm-classloader"Com.test. MainClass01 extension class loader to load directory :{}C:\Program Files\Java\jdk18.. 0 _144\jre\lib\ext Extension class loader loading directory :{}C:\WINDOWS\Sun\Java\lib\ext Process finished with exit code0

Copy the code

Three: application ClassLoader (APP ClassLoader) focus analysis

Loading responsibilities: responsible for loading. Class and JAR packages in the classpath of our project directory

This loader is also written in Java code and is a subclass of our ClassLoader. Sun.misc.Launcher$AppClassLoader is the inner class of our Launcher

String appLoadingPath = System.getProperty(“java.class.path”);

Again, we run the following code in MainClass01:

package com.test; import java.util.Arrays; import java.util.List; Public class MainClass01 {public class MainClass01 {public class MainClass01 {public class MainClass01 { public static void main(String[] args) { String appLoadingPath = System.getProperty("java.class.path"); List<String> appLoadingPathList = Arrays.asList(appLoadingPath.split(";" )); For (String appPath: appLoadingPathList) {System. Out. Println (" application class loader to load the directory: {} "+ appPath); }} "C:\Program Files\Java\jdk1.8.0_144\bin\java.exe" "-javaAgent :C:\Program Files\JetBrains\IntelliJ IDEA 2019.2\lib\idea_rt.jar=52479:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2\bin" -dfile. encoding= UTF-8-classpath "C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ charsets jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ deploy the jar. C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ access - bridge - 64. The jar. C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ cldrdata jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ DNSNS jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ jaccess jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ JFXRT jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ localedata jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ nashorn jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunec jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunjce_provider jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunmscapi jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ sunpkcs11 jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext \ zipfs jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ javaws jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ jce jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ JFR jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ JFXSWT jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ jsse jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ management - agent jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ plugin jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ resources jar; C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ rt jar; I:\ JVM \out\production\jvm-classloader" com.test.MainClass01 Application classloader loading directory :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar Application class loader to load directory :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\deploy Jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\cldrdata.jar Application class loader load directory :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\ dnnss.jar Jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jaccess.jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jfxrt.jar Application class loader loading directory :{}C: Program Files\Java\jdk1.8.0_144\jre\lib\ext\localedata.jar Application class loader loading directory :{}C: Program Files\Java\jdk1.8.0_144\jre\lib\ext\nashorn.jar Application class loader directory :{}C: Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunec.jar Jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunjce_provider. Jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunmscapi.jar Application class loader to load directory :{}C: Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunpkcs11.jar Application class loader load directory :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\zipfs.jar Jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\javaws. Jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\ jCE. jar Application class loader load directory :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar Jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfxswt.jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar Application class loader load directory :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\management-agent.jar Jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\plugin.jar :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar Application class loader to load directory :{}C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar Application classloader loading directory :{}I:\ JVMS \out\production\ JVMS -classloader loading directory :{}C:\Program Files\JetBrains\IntelliJ IDEA 2019.2\lib\idea_rt.jar Process Finished with exit code 0Copy the code

Four: our custom class loader

Therefore, the directories corresponding to the three types of loaders have been introduced, and the following will be in-depth analysis of the three types of loaders. Now let’s look at custom classloaders. Why do you need a custom class loader? Because there are scenarios where the JDK provides us with three different loaders that don’t meet our personalized needs. I’ll talk more about why. Let’s start with the custom classloader and the source code.

How do I write a custom class loader? No matter what technology you are learning in the future, it is important to know firsthand information. Because it is the most authoritative, has not undergone any processing, is also the most accurate. So let’s just look at the doc documentation in the source code.

So we have to write our own class loader, for small white must not be clear how to start. At this point, we need to think that custom class loading must be related to class loaders, but let’s see if Java provides classes related to class loaders. So we can use the IDEA editor to search, ClassLoader as the name suggests the first search. It turns out there is. This is a class loader related to the class loader, we directly read its Java doc.

I have posted the edited Chinese notes below. You can read, but here is still recommended to learn the JDK source partners or read better, so remember also more profound.

4.1: Abstract class document interpretation of ClassLoader

/** * 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 (Given a binary name for a class, such as java.lang.String is the binary name of the String class), a class loader should attempt to * locate or generate data that constitutes a definition for the A typical strategy is to transform the name into A file. 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 Convert to Java /lang/String) then the file system will find the class file based on the file name. * * <p> Every {@link Class <tt>Class</tt>} object contains a {@link* Class#getClassLoader() reference} to the <tt>ClassLoader</tt> that defined * it. * * <p> <tt>Class</tt> objects for array classes * * <p> <tt> Objects for array classes are not created by class * loaders, but are created automatically as required by the Java runtime. The Class objects for our array objects are not created by our Class loader, but by our JVM at runtime as needed.@link* Class#getClassLoader()} is the same as the class loader for its element * type; (We get the CLass object of array type, Calling getClassLoader() from this Class object returns the same as the classloader in our array element.) If the element type is a primitive type, Then the array class has no class loader. * <p> Applications implement subclasses of <tt>ClassLoader</tt> in order to * extend the manner in which the Java virtual machine dynamically loads * * <p> Class loaders may be used by security managers to indicate *  security domains. * <p> The <tt>ClassLoader</tt> class uses a delegation model to search for * classes and Resources.(ClassLoader uses the parent delegate model to find classes and resources.) Each instance of <tt>ClassLoader</tt> has an * associated parent class Classloader (a parent classloader for each instance of classloader). Requested to find a class or * resource, a <tt>ClassLoader</tt> instance will delegate the search for the * class or resource to its parent class loader before ★ ★ We need to find the * class or resource itself. Attempting to find the * class or resource itself class loader, * called the "bootstrap class loader", Does not itself have a parent but may * serve as the parent of a <tt> classLoader </tt> Instance.(Bootstrap classloaders have no parents, But it can act as a parent to other Class loaders) * <p> Class loaders that support concurrent loading of classes are known as * <em>parallel Capable </em> class loaders And are required to register * themselves at their class initialization time by invoking the * {@link* # registerAsParallelCapable < tt > this. RegisterAsParallelCapable < / tt >} * method. (if a class loader wanted to be a parallel class loader, So in the class loader is initialized when asked to call this. RegisterAsParallelCapable method) Note that the < tt > this < / tt > class is registered as Parallel * capable by default(by default the current abstract class mode of this ClassLoader is a parallel loader). However, Its subclasses still need to register themselves * if they are parallel capable. Need to register yourself as a parallel classloader) <br> * In environments In which the delegation model is not strictly * Hierarchical (if our classloaders are not in a parent-delegate model), class loaders need to be Parallel capable, otherwise class * loading can lead to deadlocks because the loader lock is held for the * duration of the class loading process (see {@linkLoadClass * <tt>loadClass</tt>} methods (loadClass< tt>loadClass</tt>} methods). The Java virtual machine classes from the local file * system in a platform-dependent manner.  For example, on UNIX systems, the * virtual machine loads classes from the directory defined by the * <tt>CLASSPATH</tt> environment * <p> However, some classes may not originate from a file. Some class files do not exist in our disk files); They may originate * from other sources, such as the network, Or they could be constructed by an * application. The method {@link#defineClass(String, byte[], int, int) * <tt>defineClass</tt>} converts an array of bytes into an instance of class * <tt>Class</tt>. Instances of this newly defined class can be created using * {Instances of this newly defined class can be created using * {@linkClass#newInstance <tt>Class.newInstance</tt>}. This instance can invoke the global delegate model through our newInstance: a class that is loaded by our classloader so that methods or constructors in that class may reference other classes, <p> The methods and constructors of objects created by a class loader may * reference other classes(). To determine the class(es) referred to, the Java * virtual machine invokes the {@link#loadClass <tt>loadClass</tt>} method of * the class loader that originally created the class. * <p> For example, an application could create a network class loader to * download class files from a server. Sample code might look like:  * <blockquote><pre> * ClassLoader loader&nbsp; = new NetworkClassLoader(host,&nbsp; port); * Object main&nbsp; = loader.loadClass("Main", true).newInstance(); * &nbsp; .&nbsp; .&nbsp; * </pre></ blockQuote > Our custom class laoder needs to rewrite our ClassLoader class findClass and our loadClassData method * <p> The network class loader subclass must define the methods {@link
* #findClass <tt>findClass</tt>} and <tt>loadClassData</tt> to load a class
* from the network. Once it has downloaded the bytes that make up the class,
* it should use the method {@link#defineClass <tt>defineClass</tt>} to * create a class instance. A sample implementation is: * <blockquote><pre> * class NetworkClassLoader extends ClassLoader { * String host; * int port; * public Class findClass(String name) { * byte[] b = loadClassData(name); * return defineClass(name, b, 0, b.length); * } * private byte[] loadClassData(String name) { * // load the class data from the connection * &nbsp; .&nbsp; .&nbsp; . * } * } * </pre></blockquote> * <h3> <a name="name">Binary names</a> </h3> * <p> Any class name provided as a {@linkString} parameter to methods in * <tt>ClassLoader</tt> must be a binary name as defined by * <cite>The Java&trade; Language Specification</cite>. * <p> Examples of valid class names include: * <blockquote><pre> * "java.lang.String" represents the binary name of our String class * "javax.Swing.jspinner $DefaultEditor" Java.security.keystore $Builder$FileBuilder$1 New Inner Class * "Java.net.urlClassLoader ($3) 1" Represents the first inner class of the third inner class in the java.net.URLClassLoader class * </pre></ blockQuote > *@see #resolveClass(Class)
* @since1.0 * /
public abstract class ClassLoader {}
Copy the code

The above documentation describes how we can implement a ClassLoader class that dynamically extends the way we load classes. As you can see from the above documentation, loading a class file requires the loadClass method and overwriting the ClassLoader class findClass and our loadClassData method

Next, translate the Java Doc for the above important methods

4.2: Our ClassLoader focuses on method details

  • LoadClass method in detail

/** * Loads the class with the specified <a href="#name">binary name</a> This method searches for classes in the * following order: * <ol> * <li><p> Invoke {@link#findLoadedClass(String)} to check if the class * has already been loaded <li><p> Invoke the {@link#loadClass(String) <tt>loadClass</tt>} method * on the parent class loader <tt>null</tt> The class * loader built-in to the virtual machine is used. instead. </p></li> * <li><p> Invoke the {@link#findClass(String)} method to find the * class. </p></li> Call our findClass method to find the class * </ol> * <p> If the class was Found using the above steps, and the * <tt>resolve</tt> flag is true, this method will then invoke the {@link* #resolveClass(Class)} method on the resulting <tt>Class</tt> object. * <p> Subclasses of  <tt>ClassLoader</tt> are encouraged to override {@link* #findClass(String)}, Rather than this method. </p> strongly requires us to subclass ClassLoader then we must write findClass method * <p> Unless overridden, this method synchronizes on the result of * {@link #getClassLoadingLock <tt>getClassLoadingLock</tt>} method
* during the entire class loading process.
* @param name
* The <a href="#name">binary name</a> of the class
* @param resolve
* If <tt>true</tt> then resolve the class
* @return The resulting <tt>Class</tt> object
* @throws ClassNotFoundException
* If the class could not be found
*/
protectedClass<? > loadClass(String name,boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// Check whether the binary name is loadedClass<? > c = findLoadedClass(name);// Not loaded
if (c == null) {
long t0 = System.nanoTime();
try {
// Check whether there is a parent class, which calls the loadClass of the parent class
if(parent ! =null) {
c = parent.loadClass(name, false);
} else {
// There is no parent class, the surface of the current class loader is already in the start class loader, so start the class loader to findc = findBootstrapClassOrNull(name); }}catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
// Not found yet
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
// Call findClass to find
c = findClass(name);

// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); }}if (resolve) {
// parse our class for join and so on
resolveClass(c);
}
returnc; }}Copy the code

There are a few important points to note in the Java Doc document above

1: loads based on binary names

2: Call findloaderClass to check if the class has been loaded

3: The parent loaderClass is called first to load

4: If the parent class is found to be null, it indicates that the top-level startup class loader has been reached

5: Next we call our findClass method to find the class

This section is the class loader loading class loading process, more important process. I hope you guys must keep in mind the source code.

Another method mentioned above

  • FindClass () method
/** * Finds the class with the specified <a href="#name">binary name</a>. This method should be overridden by class loader implementations(This method should be overridden by subclasses that follow the parent-delegate model) that * follow the delegation model for loading classes(), and will be invoked by * the {@link #loadClass <tt>loadClass</tt>} method after checking the * parent class loader for The requested class(this method is called by the loadClass method, Throws a <tt>ClassNotFoundException</tt>. * * @param name * The <a href="#name">binary name</a> of the class * * @return The resulting <tt>Class</tt> object * * @throws ClassNotFoundException * If the class could not be found * * @since 1.2 */ protected class <? > findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(name); }Copy the code
  • DefineClass () method
3.3.2 Converting a byte array into an instance of Class< TT >Class</tt>. * Before the case <tt>Class</tt> can be used it must be resolved to be used. This method * is deprecated in favor  of the version that takes a <a * href="#name">binary name</a> as its first argument, and is more secure. I don't recommend this method, I recommend rewriting it, * * @param b * The bytes that make up The class data. The bytes in positions * <tt>off</tt> through <tt>off+len-1</tt> should have the format * of a valid class file as defined by * <cite>The Java&trade; Virtual Machine Specification</cite>. * * @param off * The start offset in <tt>b</tt> of the class data * * @param len *  The length of the class data * * @return The <tt>Class</tt> object that was created from the specified * class data * *  @throws ClassFormatError * If the data did not contain a valid class * * @throws IndexOutOfBoundsException * If either <tt>off</tt> or <tt>len</tt> is negative, or if * <tt>off+len</tt> is greater than <tt>b.length</tt>. * * @throws SecurityException * If an attempt is made to add  this class to a package that * contains classes that were signed by a different set of * certificates than this class, or if an attempt is made * to define a class in a package with a fully-qualified name * that starts with "{@code java.}". * * @see #loadClass(String, boolean) * @see #resolveClass(Class) * * @deprecated Replaced by {@link #defineClass(String, byte[], int, int) * defineClass(String, byte[], int, int)} */ @Deprecated protected final Class<? > defineClass(byte[] b, int off, int len) throws ClassFormatError { return defineClass(null, b, off, len, null); }Copy the code

Both methods are explained in the comments.

After reading the Java Doc documentation above, we are ready to write a custom class loader.

The steps to create a custom class load are as follows:

1: Create a class named Test01ClassLoader, which is our own classloader

2: Inherit the ClassLoader class and override the findClass method.

3: create method loadClassData to build an array of bytes [].

4: Call the defineClass method of the parent class in findClass, passing in the relevant information (the name argument is the name, passing in the constructed byte array, starting with a subscript of 0 and ending with the array length)

5: The constructors should not be small. If it takes a parameter, it means that you specify who the parent loader is.

6: Finally, we use our custom class loader to load our specified class in main function to test…

package com.test; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; /** * findClass (); /** * findClass (); /** * (); Construct a byte[] word * 5, Call this.defineClass to create an instance of classLoader */ public Class Test01ClassLoader extends classLoader {private String classLoaderName; Private final String x = ".class"; Private String path; public void setPath(String path) { this.path = path; } /** * Use the default class loader as parent of the current class loader {APPClassLoader as parent} * @param classLoaderName */ public Test01ClassLoader(String) classLoaderName){ super(); This. ClassLoaderName = classLoaderName; } /** * Use our own class loader as the parent of the current class loader * @param parentClassLoaderNane * @param classLoaderName */ public Test01ClassLoader(ClassLoader parentClassLoaderNane,String classLoaderName){ super(parentClassLoaderNane); this.classLoaderName = classLoaderName; } /** * override the findClass method, * @param name * @return * @throws ClassNotFoundException */ @override protected Class<? > findClass(String name) throws ClassNotFoundException {system.out.println (" my class loader is loaded "); byte[] bytes = this.loadClassData(name); return this.defineClass(name,bytes,0,bytes.length); } /** * returns a byte number via the given class name * @param name * @return */ private byte[] loadClassData(String name){InputStream InputStream =  null; byte[] bytes = null; ByteArrayOutputStream byteArrayOutputStream = null; try { name = name.replace(".","\\"); inputStream= new FileInputStream(this.path+new File(name+this.x)); byteArrayOutputStream = new ByteArrayOutputStream(); int ch = 0; while(-1 ! =(ch= inputStream.read())){ byteArrayOutputStream.write(ch); } bytes=byteArrayOutputStream.toByteArray(); }catch (Exception e){ e.printStackTrace(); }finally { try { inputStream.close(); byteArrayOutputStream.close(); }catch (Exception e){ e.printStackTrace(); } } return bytes; } public static void main(String[] args) throws Exception {// Create a custom class loader instance, MyClassLoader = new Test01ClassLoader("loader1"); // Set the loading path myclassLoader. setPath("I:\\ JVM \\out\\production\\jvm-classloader\\"); // Call the loadClass method to load our class file class <? > classz = myClassLoader.loadClass("com.test.Dog"); / / Object through the constructor to create instance Object. = classz getDeclaredConstructor (). The newInstance (); System.out.println(object.getClass().getClassLoader())); /*myClassLoader.setPath("D:\\classes\\"); Class classz1 = myClassLoader.loadClass("com.jdyun.jvm05.Test"); Object object1 = classz1.getDeclaredConstructor().newInstance(); System.out.println(classz1.getClassLoader()); */ /*System.out.println(System.getProperty("sun.boot.class.path")); System.out.println(System.getProperty("java.ext.dirs")); System.out.println(System.getProperty("java.class.path")); System.out.println(Test12.getSystemClassLoader()); */ /*MyTest02[] list = new MyTest02[1]; System.out.println(list.getClass().getClassLoader()); * /}}Copy the code

The results of the above code run show that the Dog class is still loaded by AppClassLoader. So why is this? Because we specified in the constructor that the system classloader, our AppClassLoader, is our parent, the parent will load the classes that can be loaded by the parent delegate model, so our custom class load is not loaded into the Dog class. (The parental delegation model will be covered in more detail later in this article. Just keep that in mind.)

Next, let’s modify the code a bit to test if our custom class loading works.

I created a class file named test. class in G:\jdyun-jvm\out\production\jdyun-jvm\ com\ jdyun\ jvm05\\ and ran it as shown below

I changed the loading path so that our AppClassloader will only load files in the classPath path, and the files we specify externally will be automatically loaded by our custom classloader.

Next we make a small change to the code. We create two instances of our custom Class loaders and see if the Class objects are the same.

public static void main(String[] args) throws Exception {
        // Create an instance of the custom class loader and specify the name through the constructor
        Test01ClassLoader myClassLoader = new Test01ClassLoader("loader1");
        // Set the loading path
        myClassLoader.setPath("G:\\jdyun-jvm\\out\\production\\jdyun-jvm\\");
        // Call loadClass to load our class fileClass<? > classz = myClassLoader.loadClass("com.jdyun.jvm05.Test");
        // Create the instance through the constructor
        Object object = classz.getDeclaredConstructor().newInstance();
        // See which class loader loaded the instance we created
        System.out.println(classz.getClassLoader());
        System.out.println(classz.hashCode());

        // Create an instance of the custom class loader and specify the name through the constructor
        Test01ClassLoader myClassLoader2 = new Test01ClassLoader("loader1");
        // Set the loading path
        myClassLoader2.setPath("G:\\jdyun-jvm\\out\\production\\jdyun-jvm\\");
        // Call loadClass to load our class fileClass<? > classz2 = myClassLoader2.loadClass("com.jdyun.jvm05.Test");
        // Create the instance through the constructor
        Object object2 = classz2.getDeclaredConstructor().newInstance();
        // See which class loader loaded the instance we createdSystem.out.println(classz2.getClassLoader()); System.out.println(classz2.hashCode()); } printing results: its own class loader is loaded the com. Test. Test01ClassLoader @1540e19d
21685669Its own class loader is loaded the com. Test. 7 f31245a Test01ClassLoader @325040804
Copy the code

As you can see from the above code, the same Class file loaded by the same classloader does not load the same Class object. And two class objects cannot be converted to each other.

Well, everyone, let’s introduce the first article here. Now we can understand the four types of loaders. The articles on this topic will be serialized in succession.

I will write a series of articles on the principles of JVM class loading.

The art of the JVM, Class loader Part 1, is complete

The Art of the JVM – Class loader Part ii in creation

The Art of the JVM – Class loader part 3 in creation