Welcome to github.com/hsfxuebao/j… , hope to help you, if you feel ok, please click on the Star

From: www.cnblogs.com/xjwhaha/p/1…

1. Overview of JVM memory structure

What are the important components of running a JVM, as shown below

It can be divided into three major categories

  • The loading system that loads the class file into memory
  • Class storage area, program runtime memory
  • The JVM reads the class bytecode and executes the execution engine that interprets the class commands

Let’s go through them one by one

2. Class loading subsystem

Once we’ve written the code, compiled it into a bytecode class file, packaged it and run it, it’s time for the JVM to load the class using the ClassLoader.

A class file exists on the local hard disk, and can be interpreted as a template drawn on paper by the designer. The final template is loaded into the JVM at execution time, and n identical instances are instantiated from this file. And this template is what we see a lot when we use reflection, the Class object, one for each Class, that holds the metadata of that Class.

Schematic diagram:

The entire class loading process can be divided into three parts: load, link (verify -> prepare -> parse), and initialize

2.1 Loading Stage:

  1. Gets the binary byte stream that defines a class by its fully qualified name
  2. Transform the static storage structure represented by this byte stream into the runtime data structure of the method area
  3. Generate a java.lang.Class object in memory that represents the Class and acts as an access point for the Class’s various data in the method area

There are several ways to load a class file

  1. Load directly from the local system
  2. This parameter is obtained over the network. The typical scenario is a Web Applet
  3. Read from zip package, become the future jar, WAR format basis
  4. Runtime computational generation, most commonly used: dynamic proxy technology
  5. Generated by other files, typical scenario: JSP application
  6. Extract. Class files from a proprietary database, which is rare
  7. Obtained from encrypted files, a typical protection against Class files being decompiled

2.2 Link Stage:

Links are divided into three sub-stages: validation > preparation > parsing

Verify:

To ensure that the byte stream in the Class file meets the requirements of the CURRENT VM, ensure that the loaded Class is correct and does not harm vm security. It mainly includes four kinds of verification, file format verification, metadata verification, bytecode verification, symbol reference verification.

For example, bytecode files (viewed by BinaryViewer) that start with CAFE BABE will fail verification if there is an invalid bytecode file

Prepare for

  1. Allocates memory for class variables (static variables) and sets default initial values for the class variables
  2. Static with final is not included here, because final assigns a default value at compile time and is explicitly initialized during the prep phase
  3. There are also no initialization allocations for instance variables (object types), ordinary class variables are allocated in the method area, and instance variables are allocated in the Java heap along with the object

For example:

public class HelloApp { private static int a = 1; Public static void main(String[] args) {system.out.println (a); public static void main(String[] args) {system.out.println (a); }}Copy the code

Resolution (Resolve)

  1. The process of converting symbolic references in a constant pool to direct references
  2. In fact, parsing operations are often performed with the JVM after initialization
  3. 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
  4. Parsing actions are for classes or interfaces, fields, class methods, interface methods, method types, and so on. CONSTANT Class Info, CONSTANT Fieldref Info, and CONSTANT Methodref Info in the CONSTANT pool

2.3 Initialization Phase:

  1. The initialization phase is the execution of the class constructor method ()
  2. This method does not need to be defined and is a combination of the assignment actions of all class variables (static variables) automatically collected by the Javac compiler in a class and statements in a static code block. That is, when we have static variables in our code, we have the Clinit method (without static variables).

For example:

public class ClinitTest { private int a = 1; private static int c = 3; public static void main(String[] args) { int b = 2; }}Copy the code

Class has static variables that generate clinit methods

If there is no static variable

public class ClinitTest { private int a = 1; public static void main(String[] args) { int b = 2; }}Copy the code

There is no Clinit method

  1. The instructions in the () method are executed in the order in which the assignment statements appear in the source file

For example:

public class ClassInitTest { private static int number = 10; //linking: number = 0 --> initial: 10 --> 20; System.out.println(num); } public static void main(String[] args) { System.out.println(ClassInitTest.num); //2 System.out.println(ClassInitTest.number); / / 10}}Copy the code

The value of the static variable number changes as follows

  • During preparation: 0
  • Perform static variable initialization: 10
  • Execute static code block: 20

  1. <clinit>()Different from class constructors. Association: The constructor is from the virtual machine perspective<init>().)
  2. If the class has a parent class, the JVM guarantees subclasses<clinit>()Before execution, the parent class<clinit>()Execution completed
  3. The virtual machine must be guaranteed a class of<clinit>()Methods are locked synchronously in multiple threads (multiple threads loading the same class simultaneously)

Back to the top

3. Classification of class loaders

The JVM supports two types of classloaders. Bootstrap ClassLoader and User-defined ClassLoader respectively

A custom ClassLoader is conceptually 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 classifies all classloaders derived from the abstract ClassLoader as custom classloaders

No matter how class loaders are classified, the most common class loaders in a program are always only three, and the four are inclusive relationships, not the relationship between the upper and lower classes, nor the inheritance relationship between children and parents. As shown below.

Code:

Public class ClassLoaderTest {public static void main(String[] args) {// get the systemClassLoader ClassLoader.getSystemClassLoader(); System.out.println(systemClassLoader); / / sun. Misc. The Launcher $AppClassLoader @ 18 b4aac2 / / access to its upper: extension class loader this extClassLoader = systemClassLoader. The getParent (); System.out.println(extClassLoader); //sun.misc.Launcher$ExtClassLoader@1540e19d ClassLoader bootstrapClassLoader = extClassLoader.getparent (); System.out.println(bootstrapClassLoader); / / null / / for user-defined class: use the default system class loader to load this this = ClassLoaderTest. Class. GetClassLoader (); System.out.println(classLoader); //sun.misc.Launcher$AppClassLoader@18b4aac2 // The String class is loaded using the bootstrap classloader. --> Java's core class libraries are loaded using the boot class loader. ClassLoader classLoader1 = String.class.getClassLoader(); System.out.println(classLoader1); //null } }Copy the code
  • The boot class loader is null. This does not mean that the boot class loader does not exist. The boot class loader is written in C/C++ and cannot be obtained
  • Both get the same value for the system classloader: sun.misc.Launcher$AppClassLoader@18b4aac2, indicating that the system classloader is globally unique

Common loader introduction:

Start the ClassLoader (Bootstrap ClassLoader)

  1. This class loading is implemented in C/C++ and is nested within the JVM
  2. It is used to load Java’s core libraries to provide classes that the JVM itself needs
  3. Does not inherit from java.lang.ClassLoader and has no parent loader
  4. Load the Extension ClassLoader and AppClassLoade class loaders as their parent class loaders (these two loaders are also Java classes).
  5. For security reasons, Bootstrap starts the class loader to load only classes whose package names start with Java, Javax, and Sun

Extension ClassLoader

  1. Java language, implemented by sun.misc.Launcher$ExtClassLoader
  2. Derived from the ClassLoader class (or custom loader)
  3. The parent class loader is the initiator class loader
  4. Load the class libraries from the directory specified by the java.ext.dirs system property, or from the JRE /lib/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)

  1. Java language by sun. Misc. LaunchersAppClassLoader implementation
  2. Derived from the ClassLoader class (or custom loader)
  3. The parent class loader is the extension class loader
  4. It is responsible for loading the class libraries under the path specified by the environment variable classpath or the system property java.class.path
  5. Class loading is the default class loader in a program, and it is generally used to load classes in Java applications
  6. Through this. GetSystemclassLoader () method can get the class loader

Code:

public class ClassLoaderTest1 { public static void main(String[] args) { System. The out. Println (" * * * * * * * * * * to start the class loader * * * * * * * * * * * * * * "); / / get BootstrapClassLoader can load the path of the API URL [] urLs = sun. Misc. The Launcher. GetBootstrapClassPath (.) getURLs (); for (URL element : urLs) { System.out.println(element.toExternalForm()); } / / from the above path choice of a class, to see what his class loader is: the bootstrap class loader this this = Provider. Class. GetClassLoader (); System.out.println(classLoader); / / null System. Out. Println (" * * * * * * * * * * * the extension class loader * * * * * * * * * * * * * "); String extDirs = System.getProperty("java.ext.dirs"); for (String path : extDirs.split(";" )) { System.out.println(path); } / in/from the above path choice of a class, let's see what his class loader is: extension class loader this classLoader1 = CurveDB. Class. GetClassLoader (); System.out.println(classLoader1); //sun.misc.Launcher$ExtClassLoader@1540e19d } }Copy the code

Print the result

The String class is in rt.jar, loaded by the launcher class loader

The extension class loader loads jar package classes from Ext in lib

* * * * * * * * * * to start the class loader * * * * * * * * * * * * * * file: / C: / Program files/Java / % 20 jdk1.8.0 _144 / jre/lib/resources. The jar File: / C: / Program files/Java / % 20 jdk1.8.0 _144 / jre/lib/rt. The jar File: / C: / Program files/Java / % 20 jdk1.8.0 _144 / jre/lib/sunrsasign. The jar File: / C: / Program files/Java / % 20 jdk1.8.0 _144 / jre/lib/jsse. Jar file: / C: / Program files/Java / % 20 jdk1.8.0 _144 / jre/lib/jce jar File: / C: / Program files/Java / % 20 jdk1.8.0 _144 / jre/lib/charsets. The jar File: / C: / Program files/Java / % 20 jdk1.8.0 _144 / jre/lib/JFR. Jar file: / C: / Program files/Java / % 20 jdk1.8.0 _144 / jre/classes null * * * * * * * * * * * the extension class loader * * * * * * * * * * * * * C: \ Program Files \ Java \ jdk1.8.0 _144 \ jre \ lib \ ext C: \ WINDOWS \ Sun \ Java \ lib \ ext sun.misc.Launcher$ExtClassLoader@7ea987acCopy the code

Back to the top

4. User-defined loader

Note that this is a user custom, not a custom loader in the JVM specification, as outlined here and described later

Why do I need a custom class loader?

  1. Isolation of loaded classes (unused middleware, class isolation in the framework)
  2. Modify the way classes are loaded
  3. Extended load sources (loading class information from a particular environment)
  4. Prevent source code leakage (class encryption, custom loader class decryption)

How do I customize class loaders?

  1. Developers can implement their own classloaders by inheriting the abstract java.lang.ClassLoader class to meet specific needs
  2. Before JDK1.2, it was common to inherit the ClassLoader class and rewrite the loadClass() method to implement custom classloading classes. However, after JDK1.2, it is no longer recommended to override the loadClass() method. Instead, I suggest that you write your custom classloading logic in the findClass () method
  3. When writing a custom class loader, if you don’t have too complicated requirements, you can inherit the URIClassLoader class directly. This way, you can avoid writing the findClass () method and how to get the bytecode stream yourself, making the custom class loader writing simpler.

Back to the top

5. Common methods of ClassLoader

The ClassLoader class, which is an abstract class from which all subsequent classloaders (excluding the Launcher ClassLoader) are defined in the sun.misc.Launcher class. Sun.misc.Launcher is a portal application for the Java virtual machine

Common methods:

Method names

describe

GetParent ()

Returns the parent class loader of the class loader

LoadClass (String name)

Load a Class named name that returns an instance of the java.lang.Class Class

FindClass (String name)

Find the Class named name and return an instance of the java.lang.Class Class

FindLoadedClass (String name)

Find the loaded Class named name and return an instance of the java.lang.Class Class

DefineClass (String name, byte[] b,int off,int len)

Converts the contents of byte array B to a Java Class, returning an instance of the java.lang.Class Class

ResolveClass (Class <? > c)

Connects to a specified Java class

How to obtain a ClassLoader instance

  • GetClassLoader for current class: clazz.getclassloader ()
  • Thread.currentthread ().getContextClassLoader()
  • This acquisition system: this. GetSystemClassLoader ();
  • For the caller to this: DriverManager. GetCallerClassLoader ()

Code demo:

public class ClassLoaderTest2 { public static void main(String[] args) { try { //1.Class.forName().getClassLoader() ClassLoader classLoader = Class.forName("java.lang.String").getClassLoader(); System.out.println(classLoader); // The String class is loaded by the boot class loader, CurrentThread ().getContextClassLoader() ClassLoader classLoader1 = Thread.currentThread().getContextClassLoader(); System.out.println(classLoader1); //3.ClassLoader.getSystemClassLoader().getParent() ClassLoader classLoader2 = ClassLoader.getSystemClassLoader(); System.out.println(classLoader2); } catch (ClassNotFoundException e) { e.printStackTrace(); }}} // output null sun.misc.Launcher$AppClassLoader@18b4aac2 sun.misc.Launcher$AppClassLoader@18b4aac2Copy the code

Back to the top

6. Parent delegation

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’s class file, the Java VIRTUAL machine adopts parental delegation mode, that is, the request is handed over to the parent class (the parent class then delegates up until the class loader is started), which is a kind of task delegation mode

  1. 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.
  2. 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;
  3. If the parent class loader can complete the task, it returns successfully. If the parent class loader cannot complete the task, the child loader will try to load itself. This is the parent delegate mode.
  4. The parent class loader assigns tasks layer by layer, loads the class if the subclass loader can load it, and throws an exception if the application loader fails to load the class if it can’t

For example:

Create a java.lang.String class of your own that will print statements if it is loaded

package java.lang; Public class String {static{system.out.println (" I am a custom String static code block "); }}Copy the code

Load the String class in another program. The above statement is not printed. The default load is the native String class

public class StringTest { public static void main(String[] args) { java.lang.String str = new java.lang.String(); System.out.println("hello,atguigu.com"); StringTest test = new StringTest(); System.out.println(test.getClass().getClassLoader()); }}Copy the code

Because when the program needs to load the java.lang.String class, the classloader will delegate up all the time, Until the launcher loads the class, and the launcher loads the String class, the String class under native Java.lang. This will guarantee the safety of the native API and not interfere with all the places where the native API was used before because the user environment overwrites the class

Code 2

package java.lang; Public class String {static{system.out.println (" I am a custom String static code block "); Public static void main(String[] args) {system.out.println ("hello,String"); }}Copy the code

Error when running:

When the main method is loaded, it loads its host class String, which also delegates to the launcher loading class, resulting in the loading of the native String class, which has no main method

Code 3

Define custom classes in the custom java.lang package

package java.lang;

public class ShkStart {
    public static void main(String[] args) {
        System.out.println("hello!");
    }
}
Copy the code

To run an error

Because signing up for java.lang is a startup class loader, the JVM prevents custom classes from being loaded by the startup class loader to prevent custom classes from damaging the startup class loader.

From the example above, we can see that the parental mechanism can

  1. Avoid reloading classes
  2. Protect program security and prevent the core API from being tampered with
    1. Custom classes: java.lang.String are not used
    2. Custom class: java.lang.ShkStart (error: prevents creation of java.lang classes)

When we use JDBC and other third party implementation jar package, use the ClassLoader

  1. The first thing we need to know is that JDBc.jar is implemented based on the SPI interface
  2. So at load time, parent delegates are made, and eventually the SPI core class is loaded from the root loader, followed by the SPI interface class
  3. The implementation class jdbc.jar is then loaded through the thread context class loader.

Back to the top

7. Sandbox safety mechanism

When you customize a String class: Java.lang.string.jar: java.lang.string.jar: java.lang. This is because the String class is loaded in the rt.jar package. In this way, the Java core source code can be protected to ensure that the running environment of the Java core code is absolutely independent, which is the sandbox security mechanism

Related issues:

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:

  1. The full class name of the class must be consistent, including the package name
  2. The ClassLoader (ClassLoader instance object) that loads this class must be the same
  3. 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, they are not equal as long as the ClassLoader instance objects that loaded them are different

Active and passive use of classes

Java programs use classes in active and passive ways. Active use, and divided into seven cases:

  1. Create an instance of the class
  2. Accesses or assigns a value to a static variable of a class or interface
  3. Call a static method of a class
  4. Reflection (e.g. Class.forname (” com.atguigu.test “))
  5. Initialize a subclass of a class
  6. Classes that are identified as startup classes when the Java virtual machine starts
  7. JDK7 began to offer a dynamic language support: Java. Lang. Invoke. Analytical results REF_getStatic MethodHandle instance, REF putStatic, REF_invokeStatic handle corresponding class does not initialize, is initialized

In all but seven cases, the use of Java classes is considered passive and does not result in class initialization, that is, the initialization phase (the clinit() and init() methods are not called).