JVM system learning path series demo code address: github.com/mtcarpenter…
Hi, everyone, I am Brother Chun, today is punch【JVM system learning path 】
The second articleClass loading subsystem
In learning this chapter, first review the previous chapterJVM and Java Architecture
The overall structure of the JVMThis figure must bear in mind, in the following JVM knowledge points are expanded from this figure, if you know seen the JVM interview questions, we should be relatively familiar with this figure, Xiao Chun brother this figure I understand, want a more complete JVM architecture map, have? Yes, it must be satisfied. Please catch the picture below:
The JVM is a tough nut to crack, so before we eat the bone marrow, we clean it, we put it in the pot, we simmer it, we start with class loading,
Class loaders and the loading process of classes
- The classloader subsystem is responsible for loading from the file system or network
Class
File,class
Files have specific file identifiers at the beginning of the file. ClassLoader
Only responsible forclass
The loading of the file, as to whether it can run, is determined byExecution Engine
Decision.- The loaded class information is stored in a piece of memory called the method area. In addition to class information, the method area stores runtime constant pool information, possibly including string literals and numeric constants
Class
Memory mapping for the constant pool portion of the file)
class file
It exists on the local hard disk and can be interpreted as a template drawn on paper by the designer, which at the end of the execution is loaded into the JVM to instantiate n identical instances from this file.class file
Loaded into the JVM, called the DNA metadata template, is placed in the methods area.- in
.class files ->JVM-> eventually become metadata templates
This process requires a transporter (class loader)Class Loader
), play the role of a Courier
Class loading process
/** * class loading subsystem */
public class HelloLoader {
public static void main(String[] args) {
System.out.println("I'm already loaded."); }}Copy the code
This code is loaded as follows
More complete loading process, including loading, verification, preparation, parsing, initialization, as shown below:
Loading stage
- Gets the binary byte stream that defines a class by its fully qualified name
- Transform the static storage structure represented by this byte stream into the runtime data structure of the method area
- Generates an in-memory representation of this class
java.lang.Class
Object that acts as an access point to the various data of the class called the method area
How to load a class file
- Load directly from the local system
- This parameter is obtained over the network. The typical scenario is a Web Applet
- Read from zip package, become the future jar, WAR format basis
- Runtime computational generation, most commonly used: dynamic proxy technology
- Generated by other files. Typical scenario: JSP applications extract.class files from a proprietary database
- Obtained from encrypted files, a typical protection against Class files being decompiled
Link phase
Verify Verify
- The purpose is to ensure
Class
The byte stream in the file meets the requirements of the current VM, ensuring the correctness of the loaded classes and not compromising VM security. - There are four main types of validation,
File format validation
,Metadata validation
,Bytecode verification
,Symbolic reference verification
。
Tool: Binary Viewer checks to see if a class file exists. This tool will be explained later
Ready to Prepare
- Allocates memory for a class variable and sets its default initial value, zero.
public class HelloApp {
private static int a = 1; // The preparation phase is 0, and the next phase, at initialization, is 1
public static void main(String[] args) { System.out.println(a); }}Copy the code
The above variable A is assigned an initial value in the preparation phase, but instead of 1, it is 0.
- Static with final is not included here, because final is allocated at compile time and initialized explicitly during preparation;
- There is no instance variable allocation initialization, class variables are allocated in the method area, and instance variables are allocated in the Java heap along with the object.
Parsing the Resolve
- The process of converting symbolic references in a constant pool to direct references.
- In fact, parsing operations are often performed with the JVM after initialization.
- A symbolic reference is a set of symbols that describe the referenced object. The literal form of symbolic references is clearly defined in the Class file format of the Java Virtual Machine Specification. A direct reference is a pointer to a target directly, a relative offset, or a handle to the target indirectly.
- Parsing actions are for classes or interfaces, fields, class methods, interface methods, method types, and so on. Corresponds to the constant pool
CONSTANT Class info
、CONSTANT Fieldref info
、CONSTANT Methodref info
And so on.
Initialization phase
- The initialization phase is the execution of the class constructor method ().
- This method does not need to be defined; yes
Javac compiler
The assignment of all class variables in a class that is automatically collected is combined with statements in a static code block.- That is, when we include static variables in our code, we have the Clinit method
- Constructor methods execute instructions in the order in which statements appear in the source file.
- Different from class constructors. If the class has a parent class, the JVM guarantees that the parent class’s () is executed before the subclass’s () is executed.
- After any class is declared, a constructor is generated. The default is the empty parameter constructor
public class ClassInitTest {
private static int num = 1;
static {
num = 2;
number = 20;
System.out.println(num);
System.out.println(number); // Error, illegal forward reference
}
private static int number = 10;
public static void main(String[] args) {
System.out.println(ClassInitTest.num); / / 2
System.out.println(ClassInitTest.number); / / 10}}Copy the code
Class loader classification
- The JVM supports two types of classloaders. Respectively,
Bootstrap ClassLoader
和User-defined ClassLoader
。 - Conceptually, a custom class loader is a class of class loaders defined by a developer in a program, but the Java Virtual Machine specification does not define it this way. Instead, it derives everything from abstract classes
ClassLoader
Class loaders are classified as custom class loaders. - Regardless of the class loader type, what are the most common class loaders in our programs
Bootstrap ClassLoader
、Extension ClassLoader
、System Class loader (AppClassLoader)
, as follows:
The four here are inclusive relations, not the upper and lower layers, nor the inheritance of subsystems. Here is an example to get its different loaders
public class ClassLoaderTest {
public static void main(String[] args) {
// Get the system class loader
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
// Get the extension class loader on top of it
ClassLoader extClassLoader = systemClassLoader.getParent();
System.out.println(extClassLoader);
// Get the root loader
ClassLoader bootstrapClassLoader = extClassLoader.getParent();
System.out.println(bootstrapClassLoader);
// Get the custom loader
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
System.out.println(classLoader);
// Get a String loaderClassLoader classLoader1 = String.class.getClassLoader(); System.out.println(classLoader1); }}Copy the code
The above results show that the root loader cannot be obtained directly from the code, and the current loader used by the user code is the system class loader. The root loader is used to load the Java core libraries. The root loader is used to load the Java core libraries.
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@1540e19d
null
sun.misc.Launcher$AppClassLoader@18b4aac2
null
Copy the code
A built-in loader of the VM
Start the ClassLoader (Bootstrap ClassLoader)
- This class load is used
C/C + + language
Implemented, nested within the JVM. - It is used to load Java’s core libraries (
JAVAHOME/jre/1ib/rt.jar
、resources.jar
或sun.boot.class.path
To provide classes that the JVM itself needs - Does not inherit from
Java.lang.ClassLoader
There is no parent loader. - Loads extension classes and application classloaders and specifies them as parent classloaders.
- For safety reasons,
Bootstrap starts the class loader
Only the package name is loadedjava
、javax
、sun
And so on
Extension ClassLoader
- Written in the Java language by
sun.misc.Launcher$ExtClassLoader
The implementation. - Derived from
ClassLoader
类 - The parent class loader is the initiator class loader
- from
java.ext.dirs
Load the class libraries from the directory specified by the system property, or from the JRE /1ib/ext subdirectory (extension directory) of the JDK installation directory. If user-created jars are placed in this directory, they will also be automatically loaded by the extended class loader.
Application class loader (System class loader, AppClassLoader)
- Written in the Java language by
sun.misc.LaunchersAppClassLoader
implementation - Derived from
ClassLoader
类 - The parent class loader is the extension class loader
- It is responsible for loading environment variables
classpath
Or system attributesjava.class.path
Specify the class library under the path - Class loading is the default class loader in a program, and it is generally used to load classes in Java applications
- through
ClassLoader# getSystemclassLoader ()
Method to get the class loader
User-defined class loaders
- In everyday Java application development, the loading of classes is almost carried out by the above three types of loaders together. If necessary, we can also customize the class loaders to customize the way the class is loaded.
- Why custom class loaders?
- Isolation load class
- Modify the way classes are loaded
- Extended load source
- Preventing source code leakage
User-defined class loader implementation steps:
- Developers can inherit abstract classes
Java.lang.ClassLoader
Class way to implement your own class loader to meet some special needs - in
JDK1.2
Previously, when customizing class loaders, inheritance was always removedClassLoader
Class and writeloadClass()
Method to implement custom class-loading classes, but override is no longer recommended after JDK1.2loadclass()
Method, but instead suggest writing your custom classloading logic infindclass()
In the method - When writing custom class loaders, you can inherit them directly if you don’t have overly complex requirements
URIClassLoader
Class, so you can avoid writing it yourselffindclass()
Method and how it gets the bytecode stream, making custom classloader writing simpler.
View the directories that the root loader can load
public class ClassLoaderTest1 {
public static void main(String[] args) {
System.out.println("********* Start class loader ************");
// Get the API path that BootstrapClassLoader can load
URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (URL url : urls) {
System.out.println(url.toExternalForm());
}
// Select a class from the path above and see what its class loader is: null, indicating root loaderClassLoader classLoader = Provider.class.getClassLoader(); }}Copy the code
The results are as follows:
* * * * * * * * * to start the class loader * * * * * * * * * * * * file: E: / / Software/JDK18./Java/jre/lib/resources.jar
file:/E:/Software/JDK18./Java/jre/lib/rt.jar
file:/E:/Software/JDK18./Java/jre/lib/sunrsasign.jar
file:/E:/Software/JDK18./Java/jre/lib/jsse.jar
file:/E:/Software/JDK18./Java/jre/lib/jce.jar
file:/E:/Software/JDK18./Java/jre/lib/charsets.jar
file:/E:/Software/JDK18./Java/jre/lib/jfr.jar
file:/E:/Software/JDK18./Java/jre/classes
null
Copy the code
This section describes how to use ClassLoader
ClassLoader class, which is an abstract class from which all subsequent classloaders inherit (excluding the launcher ClassLoader)
methods | instructions |
---|---|
getParent() |
Returns the parent class loader of the class loader. |
loadClass(String name) |
The load name isname Class, and the return result isjava.lang.Class Class. |
findClass(String name) |
The lookup name isname Class, and the return result isjava.lang.Class Class. |
findLoadedClass(String name) |
The lookup name isname Is the class that has been loadedjava.lang.Class Class. |
defineClass(String name, byte[] b, int off, int len) |
The byte arrayb Is converted to a Java class, and the result returned isjava.lang.Class Class. This method is declared asfinal . |
resolveClass(Class<? > c) |
Link to the specified Java class. |
sun.misc.Launcher
It is a Java virtual machine entry application
How to obtain a ClassLoader
- Gets the current
This: clazz getClassLoader ()
- Gets the current thread context
This: Thread. CurrentThread (). GetContextClassLoader ()
- Access system
This: this getSystemClassLoader ()
- Gets the caller’s
This: DriverManager getCallerClassLoader ()
Parent delegation mechanism
The Java virtual machine loads class files on demand, which means that it loads its class files into memory to generate class objects when the class is needed. In addition, when loading a class file, the Java VIRTUAL machine adopts the parental delegation mode, that is, the request to the parent class processing, which is a kind of task delegation mode. The working principle of
- If a classloader receives a classload request, it does not load the request itself. Instead, it delegates the request to the parent class’s loader.
- If the parent class loader also has its parent class loader, then further delegate up, recursively, the request will eventually reach the top level of the start class loader;
- If the parent class loader can complete the class loading task, return successfully, if the parent class loader can’t complete the load task, the child loader will try to load itself, that is
Parental delegation pattern
。
Example of parent delegation mechanism
When we loadjdbc.jar
The first thing we need to know when implementing a database connectionjdbc.jar
It is implemented based on the SPI interface, so at load time, parent delegate is done, and finally the SPI core class is loaded from the root loader, then the SPI interface class is loaded, then the reverse delegate is done, and the class is implemented through the thread context class loaderjdbc.jar
The load.
Sandbox security mechanism
Java \lang\String.class (rt.jar); Java \lang\ string.class (); The error message stating that there is no main method is due to the loading of the string class from rt.jar. This ensures the protection of the Java core source code, which is called sandbox security.
Advantages of the parent delegation mechanism
From the above example, we can see that the parental mechanism can:
- Avoid reloading classes
- Protect program security and prevent the core API from being tampered with
- Custom classes:
java.lang.String
- Custom classes:
java.lang.ShkStart
Error: creation blockedjava.lang
Initial class)
- Custom classes:
How do I tell if two class objects are the same
- There are two requirements to indicate whether two class objects are the same class in the JVM:
- The full class name of the class must be consistent, including the package name.
- Load the class
ClassLoader
(i.e.,ClassLoader
Instance object) must be the same.
- In other words, in the JVM, even if these two class objects come from the same class file and are loaded by the same virtual machine, their
ClassLoader
If the instance object is different, the two class objects are not equal. - The JVM must know whether a type is loaded by the boot loader or by the user class loader. If a type is loaded by a user class loader, the JVM stores a reference to that class loader in the method area as part of the type information. When resolving a reference from one type to another, the JVM needs to ensure that the classloaders for both types are the same.
Active and passive use of classes
Java programs use classes in active and passive ways.
- Active use, and divided into seven cases:
- Create an instance of the class
- Accesses or assigns a value to a static variable of a class or interface
- Call the static method I of the class
- Reflection (e.g.
Class.forname (" com. Atguigu. Test"
)) - Initialize a subclass of a class
- Classes that are identified as startup classes when the Java virtual machine starts
- Dynamic language support for the beginning of JDK7:
java.lang.invoke.MethodHandle
The parsing result of the instanceREF getStatic, REF putStatic, and REF invokeStatic
If the class corresponding to the handle is not initialized, it is initialized
- Except for these seven cases, any other way of using A Java class is considered a passive use of the class and does not result in class initialization.
conclusion
This article begins by reviewing the JVM structure diagram and perfecting the complete STRUCTURE diagram of the JVM, and then begins to learn about class loading. The process of class loading is divided into three stages: loading stage (bootstrap class, extension class, system class loader), linking stage (verification, preparation, parsing), and initialization stage. Next, we also introduced the virtual machine loader, startup class loader, extension class loader, reference class loader. One of the more frequently asked questions is about parental delegation.
Welcome to pay attention to the public number Shanma carpenter, I am Xiao Chun brother, engaged in Java back-end development, will be a little front-end, through the continuous output of a series of technical articles to literary friends, if this article can help you, welcome everyone to pay attention to, like, share support, we see you next period!