An overview of the
Java files are eventually compiled into Class files, which need to be loaded into the JVM to run and use. The VIRTUAL machine loads the Class file describing the Class into memory, verifies the data, converts, parses and initializes the data, and finally forms Java types that can be directly used. This is the Class loading mechanism of virtual machines
In the Java language, class loading, linking, initialization, are carried out at runtime, although this will increase some performance overhead, but will make the Java program more flexible, Java can naturally dynamically extend the language features is to rely on the runtime dynamic loading and dynamic linking to achieve
Class loading timing
The whole life cycle of a class consists of seven stages: load, verify, prepare, parse, initialize, use, and unload. The three parts of verify, prepare, and parse are collectively referred to as connections
Which load, validation, preparation, initialization, unload the five phase is to determine the beginning of the order, the beginning of the class loading process must, in accordance with the order on track, while parsing is not sure, he can in some cases after initialization, note that there is a start, we say rather than on or complete, emphasize this point because these stages is the completion of the cross, Usually one phase is activated while another phase is in progress
Class loading process
Let’s take a look at the whole process of class loading
loading
Loading is a phase of class loading, so don’t confuse the two concepts
The load phase does three things
- 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 a method area runtime data structure
- Generate a java.lang.class object in memory as an access point to the data of the class in the method area
These three definitions are not specific. The first one fetches the binary stream that defines this class by the fully qualified name of a class, without specifying where or how to fetch it. This gives the developer a lot of flexibility, such as
- We can get it from ZIP, such as a JAR
- We can get it from the Internet
- Runtime computing generation is the scenario that makes the most use of dynamic proxy techniques
- .
After the loading phase is complete, the binary stream outside the virtual machine is stored in the method area in the format required by the virtual machine, and then a java.lang.class object is instantiated, although it is an object, but it exists in the method area
validation
Validation is the first step in the connection phase, which ensures that the byte stream of the Class file contains information that meets the requirements of the current virtual machine and does not compromise the security of the virtual machine
To prepare
The preparation phase is the formal allocation of memory for class variables (static variables) and the setting of initial values. The memory used by these variables will be allocated in the method area. Here we focus on the initial values, such as the following variable
public static int value=123;
Copy the code
This phase assigns it a value of 0, not 123, because no Java methods have been executed yet. Assigning a variable to 123 is only executed during initialization, as listed below, with zero values for Java primitive data types
parsing
The parsing phase is the process by which the virtual machine replaces symbols in the constant pool with direct references
Initialize the
Initialization is the last step of class loading. In the previous class loading process, except for the loading stage, the user can control the other actions are dominated by the VIRTUAL machine. In the initialization stage, the Java program code defined in the class is actually executed
Regarding the initialization phase of class loading, there are only five scenarios where classes must be initialized in the VIRTUAL machine specification:
- When an object is instantiated with the new keyword, a static field (excluding compile-time constants) is read or set, and a static method is called, the class load initialization process (the final phase of the class load) must be triggered.
- When a class is called using reflection, it is initialized if the class is not already initialized
- When initializing a class, if the parent class has not already been initialized, initialization of the parent class is triggered first
- When the Java virtual machine starts, the user needs to specify a main class (the class containing the main method) to execute, and the virtual machine initializes this main class first
- When using dynamic language support in JDK 1.7, if a
java.lang.invoke.MethodHandle
The final parsing result of the example isREF_getStatic, REF_putStatic, REF_invokeStatic
Way to handle, and the method to handle the corresponding class does not initialize, must trigger the initialization (that don’t understand calculate, this is the new 1.7 dynamic language support, its key feature is the main body of its type checking process was conducted at runtime rather than compile time, this is a relatively larger topic, here for a moment to stop)
Classes and class loaders
The virtual machine implements the class-loading process of retrieving the binary stream that defines a class by its fully qualified name outside the Java virtual machine, allowing the user to decide how to retrieve the desired class. The block of code that implements this action is called a classloader
Although the Class loader is most used in the loading phase of a Class, its role in The Java program is not limited to the loading phase of a Class. For example, how to determine whether two classes are equal and only two classes are loaded by the same loader is meaningful. Otherwise, even if two classes come from the same Class file and are loaded by the same VIRTUAL machine, As long as the class loaders that load them are different, two classes must not be equal
Equality includes the equals method of the Class object and the Instance of keyword
Parental delegation model
From a Java virtual machine perspective, there are only two different class loaders
- One is to start the Bootstrap ClassLoader, which is implemented in C++ as part of the virtual machine itself.
- The other is all the other classloaders implemented by the Java language, independent of the virtual machine, and all inherited from java.lang.classloader
From the Java developer’s point of view, class loaders can be divided a little more subtly, and most use three of the following
Bootstrap ClassLoader (start column loader)
This class loader is responsible for loading libraries recognized by the virtual machine into the vm memory that are placed in the
\lib directory or in the path specified by the -xbootCLASspath parameter
Java virtual machine startup is accomplished by creating an initial class by starting the class loader, which is not accessible by Java code because it is implemented in C++
Extension ClassLoader
It is responsible for loading files in the
\lib\ext directory, or all libraries in the path specified by the java.ext.dirs system variable. Developers can use the extended class loader directly, the implementation class ExtClassLoader in Java
Application ClassLoader
Since this ClassLoader is the return value of the getSystemClassLoader method in ClassLoad, it is also called the system ClassLoader. It is responsible for loading the class libraries specified in the user’s classpath. Developers can use it directly if they do not customize the ClassLoader. This is the program’s default class loader, the implementation class AppClassLoader in Java
The hierarchy of class loaders shown in the figure below is called the parent delegate model. The parent delegate model requires that in addition to the top level of the starting class loader, the parent loader should have its own parent loader, which is implemented as a parent-child relationship, not as inheritance, but as a combination
Parents delegate the working process of the model
If a class loader has received the load request, he won’t try to load the first class, but to delegate the request to the parent class loader is complete, each level of the loader, so all the load request, should be introduced to the top of the boot loader, only the parent class loader feedback, unable to complete the load request, The loader will try to load it itself
Benefits of the parental delegation model
- Avoid reloading. If it is already loaded, it does not need to be reloaded
- Security, if you define
String
Class in place of the systemString
Class, which leads to risk, but in the parent delegate model,String
Class injava
The virtual machine is loaded as soon as it starts, you customize itString
Classes are not loaded
Parent delegate model implementation source code
protectedClass<? > loadClass(String name,boolean resolve)
throws ClassNotFoundException{
// First check if the class is loadedClass<? > c = findLoadedClass(name);if (c == null) {
try {
if(parent ! =null) {
c = parent.loadClass(name, false);
} else{ c = findBootstrapClassOrNull(name); }}catch (ClassNotFoundException e) {
// If the parent throws a ClassNotFoundException
// The parent class cannot load the class
}
if (c == null) {
// If the parent class cannot be loaded, call its own findClass to addc = findClass(name); }}return c;
}
Copy the code
If not, call the parent’s loader. If the parent’s loader is empty, call the start loader. If the parent’s loader fails, call its own findClass load
In Java this
There are three types of classloaders, but there are more than three classloaders provided by the system. The ClassLoader is implemented as a parent-child relationship, not as an inheritance, but as a combination of classloaders.
These five classloaders are introduced as follows:
- ClassLoader: is an abstract class, defined
ClassLoader
The main functions of - SecureClassLoader: inherits abstract classes
ClassLoader
, butSecureClassLoader
notClassLoader
The implementation class is an extensionClassLoader
Class has been enhanced by adding permissionsClassLoader
The safety of - UrlClassLoader: inherited from
SecureClassLoader
, you can load classes and resources from JAR files and folders through the Url path - ExtClassLoader and AppClassLoader: inherited from
URLClassLoader
They all areLauncher
Inner class of,Launcher
Java Virtual Machine entry application,ExtClassLoader
andAppClassLoader
Is in theLauncher
Is initialized in
The custom this
The ClassLoader provided by the system can only load classes in a specified directory. To load Class files in a folder on the network or disk, you need to customize a ClassLoader. There are two steps to implement ClassLoader
- Define a class and inherit
ClassLoader
- rewrite
findClass
Method, and infindClass
Method calldefineClass
methods
public class CustomClassLoader extends ClassLoader {
private String path;
public CustomClassLoader(String path) {
this.path = path;
}
@Override
protectedClass<? > findClass(String name)throws ClassNotFoundException {
Class clazz;
/ / comment 1
byte[] data = loadClassData(name);
if (data == null) {
throw new ClassNotFoundException();
} else {
/ / comment 2
clazz = defineClass(name, data, 0, data.length);
}
return clazz;
}
private byte[] loadClassData(String name) {
String fileName = getFileName(name);
File file = new File(path,fileName);
InputStream in=null;
ByteArrayOutputStream out=null;
try {
in = new FileInputStream(file);
out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length=0;
while((length = in.read(buffer)) ! = -1) {
out.write(buffer, 0, length);
}
return out.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(in! =null) { in.close(); }}catch (IOException e) {
e.printStackTrace();
}
try{
if(out! =null) { out.close(); }}catch(IOException e){ e.printStackTrace(); }}return null;
}
private String getFileName(String name) {
int index = name.lastIndexOf('. ');
if(index == -1) {// If no '.' is found, add the. Class at the end
return name+".class";
}else{
return name.substring(index+1) +".class"; }}}Copy the code
The ClassLoader is a custom loader.
- Note 1: The loadClassData method gets the bytecode array of the class file
- Note 2: The defineClass method converts a class bytecode array into an instance of a class class
Let’s verify that it works
Define a hello.java file on your disk
package com.baidu.bpit.aibaidu.lib;
public class Hello {
public void say(a) {
System.out.println("helloword"); }}Copy the code
Use the command line to go to your disk and execute javac hello.java to generate the hello.class file. Then create a Java Library in AS to test
public class MyClass {
public static void main(String[] args) {
/ / comment 1
CustomClassLoader customClassLoader = new CustomClassLoader("/Users/v_renxiaohui01/Desktop");
try {
/ / comment 2Class<? > aClass = customClassLoader.findClass("com.baidu.bpit.aibaidu.lib.Hello");
if(aClass ! =null) {
try {
Object o = aClass.newInstance();
System.out.println(o.getClass().getClassLoader());
Method say = aClass.getDeclaredMethod("say".null);
/ / comment 3
say.invoke(o, null);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch(InvocationTargetException e) { e.printStackTrace(); }}}catch(ClassNotFoundException e) { e.printStackTrace(); }}}Copy the code
- Comment 1: Pass the path to the class to load
- Note 2: Load
class
file - Note 3: Called by reflection
Hello, the say
methods
Look at the log
com.baidu.bpit.aibaidu.lib.CustomClassLoader@677327b6
helloword
Copy the code
Reference: Understanding the Java Virtual Machine in Depth
Blog.csdn.net/itachi85/ar…