Remember when the interviewer casually asked, "Do you know classloading in Android?" I: Remember, bar bar bar bar...... Interviewer: Well, that's all for today's interviewCopy the code

Later I went home to check the information and found out that it was related to Java, not Android. Now I am sorting out the contents of both again

Java

We know that Java passes. Java source files passjavacClass bytecode, which is then processed by the JVMBefore we talk about Java class loading, let’s take a look at bytecode, which has a lot to do with the class loading mechanism.

The bytecode

Computers only know zeros and ones, so any language needs to be compiled into machine code to be understood and executed by computers, and Java is no exception, which is why we compile into.class files via Javac

Let’s take a look at what Java bytecode looks like.

public class Test{
	public static void main(String[] args){
    	System.out.println("i am just test"); }}Copy the code

After the code is compiled, a test. class bytecode file is generated, which can then be viewed using XXD test. class

Cafe Base is a symbol of the JVM’s recognition of a. Class file. It is an important part of the class loading process

What is class loading

Now that we know about bytecode, what is class loading?

Loading a class means reading the binary data from the class’s.class file into memory, placing it in the method area of the runtime data area, and then creating a java.lang. class object in the heap that encapsulates the data structure of the class in the loading method area. It also provides developers with an interface to the data structure in the cube

The process of class loading

The life cycle of a class from the time it is loaded into virtual machine memory to the time it is unloaded includesLoad -> Verify -> Prepare -> Parse -> Initialize -> Use -> UninstallThere are seven stagesVerify -> Prepare -> ParseCollectively referred to asThe connection, the sequence is shown in the figure

Note:

Loading, validation, preparation, parsing and initialization through five stages, the loading, validation, preparation, and are not necessarily the order of initialization is certain phase, it can sometimes be started after the initialization phase That is to say, these are in accordance with the order, but don't be carried out in accordance with the order and completed Usually because they were cross each otherCopy the code

Let’s talk a little bit about these processes

load

Loading: Loading is the first step in the class loading process, that is, reading the binary data from the bytecode into memory after it is compiled by javAC, that is, what class loading is above.

To summarize, virtual machines accomplish three main things:

The binary data in the.class file is read into memory. The static storage structure of the byte stream is converted into the runtime data structure in the method area. The java.lang. class object is created in the heap and interfaces to the data structure in the method areaCopy the code
validation

Validation is the first step in the connection phase

The purpose of validation is to ensure that the loaded classes are correct and do not cause harmful behavior to the JVM.

Mainly completed four stages of verification:1. Verification of file format:

Verify that the.class file byte stream complies with the class file specification and can be processed by the virtual machine. Validation includes checks for magic numbers, version numbers, constant pools, etc. (magic numbers and version numbers are included in the.class file)Copy the code

2. Metadata verification:

It mainly carries on the semantic analysis to the bytecode description information to ensure that it conforms to the Java language specificationCopy the code

3. Bytecode verification:

It is the most complex stage in the verification process, mainly through data flow and control flow analysis, to determine whether the program syntax is legal, whether it is logical, but also to avoid suspicion at runtime harm to the JVMCopy the code

4. Symbol reference check:

Is the final stage in the validation process, which is performed primarily when the JVM converts symbolic references to direct references. It mainly verifies information outside the class itself to ensure that the parsing action is completedCopy the code
To prepare

The preparation phase is mainly about allocating memory and setting initial values for class variables

Class variables (static) allocate memory, but instances do not. Instance variables are allocated to the Java heap when the object is instantiatedCopy the code

If say

public static int value = 10
Copy the code

Here the value of int is 0, not 10. The operation assigned to 10 is in the initialization phase

So let’s say the code looks like this

public static final int value = 10
Copy the code

Note that when both static and final are modified, the value at this point is 10

Because both static and final modifiers put the result into the class’s constant pool at compile time

parsing

The parsing phase is the process of turning symbolic references into direct references

Symbolic reference: a set of symbols, any literal, describing the target of the reference direct reference: the symbolic reference is parsed to find the corresponding actual memory addressCopy the code

Parsing is mainly for class, interface, field, class method, interface method, method type, method handle, and call point qualifier 7 class symbol references

Initialize the

Initialization is the last step in the class loading process, performed on static variables and static code blocks of the class

At this stage, the Java program will actually start executing. We know that we have assigned values to class variables once during the preparation stage, so we can assign values as needed during this stage

This stage is the execution of the class constructor’s

() method, which simply performs the new operation

When is the class initialized

3) call a static method of the Class. 4) Reflect (class.forname (" XXXX ")) 5) initialize a subclass of a Class. 6) Start the Class as specified when the JVM starts. That is, the class with the same file name and class nameCopy the code

Class initialization steps

1) If the class has not been loaded and linked, the load and link will be performed first. 2) If the class has a direct parent, and the class has not been initialized (note: In a classloader, classes can only be initialized once), then initialize the immediate parent class (not for interfaces). 3) If static variables and static blocks are present in the class, perform these initializations in sequenceCopy the code

The way classes are loaded

1) Load directly from the local system 2) Download. Class files from the network 3) Load. Class files from zip, JAR files 4) Extract. Class files from a specialized database 5) Compile Java files to obtain. 7) Use the classloader.loadClass () method to loadCopy the code

Class loader

JVM class loading is done by ClassLoader and its subclasses, and the class hierarchy and loading order are as follows:The parent delegate model is used here, and loading from the top parent class is preferred to ensure the stable running of Java programs

We can see which loader type we currently belong to by using the object.getClassLoader () method

Parent delegation mechanism

  • concept

When a classloader loads a.class file, it first passes the task on to the parent classloader, recurses the operation, and if it doesn’t find it, loads the class itself

  • Code logic (pseudocode)
public void loadClass(String name){
     //1. Check whether it is loaded
     Class c=findLoadedClass(name);
     
     if(parent! =null) {//2. If the parent class exists, the parent class is processed
     	c=parent.loadClass(name);
     }else{
     	//3. If it does not exist, submit it to the initiator
     	c=findBoostrapClass0(name);
     }
     //4. Otherwise, handle it yourself
     c=findClass(name);
}

Copy the code

That’s it for Java class loading. Now let’s look at Android

Android

Before we talk about the Android class loading mechanism, let’s take a look at the Android VIRTUAL machine

JVM vs Dalvik

Android applications run on the Dalvik/ART VIRTUAL machine, and each application should have a separate Dalvik VIRTUAL Machine instance.

The Dalvik virtual machine is actually a Java virtual machine, but it executes a.dex file instead of a.class file in Java

The Dalvik VIRTUAL machine and the Java virtual machine share similar features, but the difference is that they execute different instruction sets. Java VIRTUAL machine is based on stack, while Dalvik is based on register

So what is a stack-based virtual machine? What is a register-based virtual machine?

  • Stack-based virtual machines

For stack virtual machines, there is a separate stack for each thread at run time. The stack records the history of method calls, and each time a method is called, an additional stack frame is added to the stack. The top stack frame is called the current stack frame and represents the currently executing method.

Stack-based virtual machines do all their operations by manipulating data

  • Register-based virtual machines

Register-based virtual machines have no operand stack, but many virtual registers, the same as operand stacks, that are stored in the stack at run time, essentially an array. Similar to the JVM, each thread in the Dalvik VM has its own PC(program counter) and call stack, where the activity record of method calls is stored in frames

  • Stack virtual machine vs register virtual machine

Compared to the JVM, the Dalvik callers were found to have fewer instructions and fewer data movements

The comparison is as follows:

Compare the content of Stack call Register – type call
Article order number more less
The code size small more
portability optimal bad
Order to optimize Not easy to easy
Explain execution speed slow fast
Code generation difficulty easy complex
Data movement times more less

ART & Dalvik

The Dalvik virtual machine executes dex bytecode and interprets execution. From Android2.2, support for just-in-time (JIT) compilation, In the process of running the application to select hot (frequently executed) code for compilation or optimization

ART(Android Runtime) is a developer option introduced in Android4.4 and the default Android Runtime for Android5.0 and later.

ART VIRTUAL machine executes the local machine code, Android runs the replacement of Dalvik VIRTUAL machine into ART virtual machine, the developer is unaware of the operation, APK still contains dex bytecode files

Do you know where the local machine code executed by the ART virtual machine comes from? (Hint: Dex2aot)Copy the code

How Android N works

On Android N, ART uses a mix of pre-aOT compilation, interpreted execution, and JIN

The benefits of this approach:

1. The application is initially installed without any AOT compilation (installation is faster), execution is interpreted during execution, and methods executed by the process are JIT compiled and recorded in the Profile

2. When the device is idle and charging, the compilation daemon will run, AOT compiling common code according to the Profile file, and wait for the next run

Let’s use a hot repair diagram to illustrate this process

Class loader

In my opinion, Android class loading mechanism is similar to Java class loading mechanism, the difference is that they load different files, so now let’s look at Android class loading mechanism

In Android, BootClassLoader and BaseDexClassLoader are generally classified. Based on BaseDexClassLoader, PathClassLoader and DexClassLoader are derived

  • Class inheritance diagram

ClassLoader is an abstract class. Its concrete implementation classes are:

BootClassLoader: used to load the Class of the Android Framework layer. BaseDexClassLoader: used to load the class of Android programs. Dex 3.DexClassLoader: loads the specified dex, classed. Dex in jar, ZIP, and APK 4.PathClassLoader: loads the specified dex and classed.dex in JAR, ZIP, and APKCopy the code

PathClassLoaderandDexClassLoaderAll of the parent classes ofBaseDexClassLoaderSo what’s the difference between them?

The only difference is that DexClassLoader creates an optimizesDirectory parameter and creates a File object to pass to super, while PathClassLoader can pass NULL directly

Notice that there is no difference after API26(android 9.0)

  • Parent delegate process

Note:

c=findBootstrapClassLoaderOrNull(name)

When parent is null, classes loaded by BootStrapClassLoader can also be loaded

If new PathClassLoader(“/sdcard/xxx.dex”,null) can load activity.class? In fact:

private Class findBootstrapClassLoaderOrNull(String name){
	return null;
}
Copy the code

Android is different from Java here

  • How is Activty loaded

We get the current PathClassLoader in MainActivity using the getClassLoader() method, so we can look at the methods in the PathClassLoader

public class PathClassLoader extends BaseDexClassLoader{}
Copy the code

Since PathClassLoader is an inherited BaseDexClassLoader, we can directly look at the BaseDexClassLoaderfindClassMethod, how is it implemented

The implementation is simple, look up the class from the pathList, and we continue to look at DexPathListTo viewmakeDexElements()Method finally found that the implementation isGo to List<File>.add(dexPath) and use DexFile to load the dex File and return the Element array

LoadBinaryName = Dex loadBinaryName = Dex loadBinaryName = Dex loadBinaryName = Dex loadBinaryName = Dex loadBinaryName = Dex loadBinaryName = Dex loadBinaryName = Dex loadBinaryName

The above briefly describes the loading process of a class, and finally summarizes it with a flow chart:

By the way, a hot fix does this by inserting the patch pack at the top of the classex.dex file and letting it execute first

In my opinion, Java and Android have the same class loading mechanism. They both load classes through the parent delegate mechanism, but load different files

Benefits of the parent delegate mechanism

1. Prevent repeated loading of the same class file to ensure data security

2. Ensure that the core class will not be tampered with, through the way of delegation search, even if tampered with can not be loaded, to ensure the security of class execution

conclusion

By comparing the way of learning for class loading mechanism I have a deeper understanding, about learning can not only learn, but also crazy output, crazy ~ output