Android performance tuning needs to master the JVM knowledge, advanced Android development to strengthen the actual combat

  • Bootstrp ClassLoader (bootstrap class loader)

The Bootstrp loader is written in C++ language. It is initialized after the JVM is started. It is mainly responsible for loading %JAVA_HOME%/jre/lib, -Xbootclasspaththe path specified by the parameters, and the classes in %JAVA_HOME%/jre/classes.

Because it is written in C++, it cannot be accessed by Java code, but you can check whether a class has been loaded by the bootstrap class loader.

  • Extensions ClassLoader (extension class loader)

Bootstrp Loader loads ExtClassLoader, and sets its parent loader (it is the parent loader instead of the parent class) as itself. This ExtClass Loader is written in java. It mainly loads all the classes directories under this path and the path specified by the system %JAVA_HOME%/jre/lib/extvariable java.ext.dirs. class library.

  • Application ClassLoader (application class loader)

After Bootstrp Loader loads ExtClassLoader, it will load AppClassLoader and specify its parent loader as ExtClassLoader. Its function is to load the current application directory Classpathand java.class.paththe class or jre file specified by the system property. It is also the default loader for Java.

We will write an article about the knowledge of ClassLoader later to deepen our understanding

4 Runtime data area

==========================================================================

Java's memory is not just heap memory and stack memory.

1. Program Counter

In order to ensure that the program can continue to execute, the processor must have some means to determine the address of the next instruction. And the program counter does just that.

The program counter, also called the PC register, is a small memory space. In the virtual machine conceptual model, the bytecode interpreter works by changing the program counter to select the next bytecode instruction to be executed.

The multi-threading of JVM is realized by switching in turn and allocating processor execution time. Only one processor executes the instructions in a thread at a certain moment . In order to restore the correct execution position after thread switching, each thread will have an independent program counter, so the program counter is private .

If the method executed by the thread is not a native method, the program counter is saved at the address of the bytecode instruction being executed, otherwise the value of the program counter is empty. The program counter is the only data area in the JVM specification that doesn't have any OOM situations

2. Java virtual machine stack

Each Java virtual machine thread has a thread-private Java virtual machine stack. Its lifecycle is the same as a thread.

The Java virtual machine stack stores the state of the Java method call in the thread, such as local variables, parameters, return values, and intermediate results of operations.

A Java virtual machine stack contains multiple stack frames , and a stack frame is used to store information such as local variables, operand stacks, dynamic links, and method exits . When a thread calls a Java method, the virtual machine pushes a new stack frame into the thread's Java virtual machine stack. After the method is executed, the stack frame is popped from the Java virtual machine stack.

Two exceptions are defined in the Java Virtual Machine Specification:

  1. If the stack capacity allocated by the thread request exceeds the maximum capacity allowed by the Java virtual machine, the Java virtual machine will throw a StackOverflowError, that is, the stack will explode.

  2. If the JVM stack can be dynamically expanded, but cannot apply for enough memory when expanding, or when creating a new thread, there is not enough memory to create the corresponding JVM, an OutOfMemoryError exception will be thrown, that is, OOM

Because most JVMs are scalable, we see more OOMs than stack bursts.

3. Native method stack

The JVM may use C Stacks to support the Native language. This C Stacks is the native method stack.

It is similar to the JVM stack, except that the local method stack is used to support the Native method. If the Java virtual machine does not support the Native method and does not depend on the C Stacks, it does not need to support local development. The Jvm can freely implement the local method stack, for example, the HotSpot VM combines the local development and the Java virtual machine stack into one.

The native method stack also throws StackOverflowError and OutOfMemoryError exceptions.

4. Java heap

The Java heap is a runtime memory area shared by all threads. The Java heap is used to store object instances.

Almost all object instances allocate memory here. Objects stored in the Java heap are managed by the garbage collector, and these managed objects cannot be explicitly destroyed.

From the perspective of memory recovery, the Java heap can be roughly divided into the new generation and the old generation .

From the perspective of memory allocation, multiple thread-private allocation buffers may be divided in the Java heap.

An exception is defined in the Java Virtual Machine Specification: If there is not enough memory in the heap to complete the instance allocation, and the heap cannot be expanded, an OutOfMemoryError exception will also be thrown.

5. Method area

The method area is a memory area shared by threads, and is used to store the structural information of classes that have been loaded by the Java virtual machine. Including runtime constant pool, field and method information, static variables and other data. The method area is a logical part of the Java heap. It is also not physically contiguous, and you can choose not to implement garbage collection in the method area.

The method area is not equal to the permanent generation, just because the HotSpot VM uses the permanent generation to implement the method area. For other JVMs, such as J9 and JRockit, there is no such concept as the permanent generation.

If the method area does not meet the memory allocation requirements, the JVM will also throw an OOM exception.

6. Runtime constant pool

Not part of the runtime data area, but part of the method area.

As we saw in the previous Class file structure, the Class file not only contains the version number, interface, fields, etc. of the class, but also contains the constant pool.

It is used to store literals and symbol references generated during compilation , which will be stored in the runtime constant pool in the method area after the class is loaded.

The runtime constant pool can be understood as the runtime representation of the constant pool of a class or interface.

5. Object creation

========================================================================

The creation of objects is something we often do, usually through the new instruction to complete the creation of an object, when the virtual machine receives a new instruction, it will do the following operations:

  1. Determine whether the class corresponding to the object is loaded, linked and initialized

  2. allocate memory for the object

After the class loading is complete, a block of memory will be allocated to the object in the Java heap Memory allocation is based on whether the Java heap is regular. There are two ways:

(1) Pointer collision, if the memory of the Java heap is regular, that is, all used memory is put aside, and free memory is put aside. When allocating memory, move the pointer in the middle to the free memory for a distance equal to the size of the object, so that the work of allocating memory is completed

(2) Free list, if the memory of the Java heap is irregular, a list needs to be maintained by the virtual machine to record which memory is available.

In this way, a large enough memory can be queried from the list to allocate to the object during allocation.

Whether the memory of the Java heap is regular or not depends on whether the garbage collector used has the function of compacting and sorting.

  1. Dealing with Concurrency Security Issues

Creating an object is a very frequent operation, so there are two ways to solve the concurrency problem:

(1) Synchronize the action of allocating memory space, such as using the CAS algorithm in the virtual machine and adding a failed retry method to ensure the atomicity of the update operation

(2) Each thread pre-allocates a small piece of memory in the Java heap. This piece of memory becomes the local thread allocation buffer. When a thread needs to allocate memory, it allocates memory on the TLAB of the corresponding thread. When a new TLAB is allocated, synchronization lock is only required at this time. Use the -XX:+/-UserTLAB parameter to set whether the virtual machine uses TLAB.

  1. Initialize the allocated memory space

Initializes the allocated memory, except for the object header, to a zero value

  1. Set the object header of the object

Store data such as the class of the object, the HashCode of the object, and the GC generation age of the object in the object header of the object.

The knowledge of the object header will be sorted out later

  1. Execute the init method to initialize

Execute init(), initialize the member variables of the object, call the constructor of the class, and an object is created.

PS: From the above alone, we can know that creating an object will actually cause a certain cost, so after reading these things, will you easily go to the new object? Will you go to the new object in onDraw()? So please also consider object creation as a minor operation!

4.1 Heap memory layout of objects


We already know that the object is created, and the heap allocates space for the object, so how is the object laid out in the heap memory, and what does it look like? As mentioned in the previous section, what is the object header?

Taking HotSpot VM as an example, the layout of objects in the heap memory is divided into three areas:

  1. object header

The object header includes two parts of information, namely Mark Word and metadata pointer

(1) Mark Word: Used to store object runtime data, such as Hash Code, lock status flag , CG generational age, and locks held by threads

(2) Metadata pointer: used to point to the metadata of the target class in the method area, through which the specific type of the object can be determined. I will talk about it later

  1. instance data

Used to store various types of field information in objects (including those inherited from parent classes)

  1. Align padding

Alignment padding does not necessarily exist, it acts as a placeholder and has no special meaning.

The implementation class of Mark Word in HotSpot is that markOop.hppmarkOop is designed as a non-fixed data structure, which is to store as much data as possible in a very small space.

The markOop format of the 32-bit virtual machine is as follows:

//32-bit markOop

hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)

JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)

size:32 ------------------------------------------>| (CMS free block)

PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)

The interpretation of the data is:

  1. hash

object's hash code

  1. age

The generational age of the object

  1. biased_lock

Bias lock flag

  1. lock

lock status flag

  1. JavaThread*

Id of the thread holding the biased lock

  1. epoch

Bias timestamp

Mark Word is often used to study the status of locks. When I was doing my understanding of object locks, I also wrote about this kind of thing, but the angle is different. It is traced from the lock to the Mark Word, and here is traced from the Mark Word to the lock. , I won’t go into details about locks here, here are two articles: Several lock mechanisms in Java

Synchronized lock optimization

Here is a summary:

The startup of a process can generate a JVM, and there are multiple threads on a JVM. When the program is running, the heap on the JVM will allocate memory space for many objects.

When a thread wants to use an object on the heap, it will first access the Mark Word of the object to see if the lock, the class lock, and the object lock can be used (that is, whether it is used by another thread) ), if it can be used, use it, if not, spin/wait according to the state of the lock or ...

4.2 oop-klass model


oop-klass is a model used to describe Java object instances, which is divided into two parts:

  1. OOP(Ordinary Object Pointer)

Refers to the ordinary object pointer, which is used to represent the instance information of the object.

  1. klass

klass is used to describe metadata

The oop-klass model is adopted in HotSpot. oop is actually a family. Many oop types are defined inside the JVM, as follows:

typedef class markOopDesc* markOop; //oop mark object

typedef class oopDesc* oop; //top parent class of oop family

typedef class instanceOopDesc* instanceOop; //Indicates a Java class instance

typedef class arrayOopDesc* arrayOopDesc*; //array object

typedef class objArrayOopDesc* objectArrayOopDes //reference type array object

typedef class typeArrayOopDesc* typeArrayOop; //basic type array object

Where oopDesc ​​is the top-level parent class of all oops, and arrayOopDesc ​​is the parent class of objArrayOopDesc ​​and typeArrayOopDesc.

Both instanceOopDesc* and arrayOopDesc ​​can be used to describe the object header.

The klass family is also defined:

class Klass; //parent class of the klass family

class InstanceKlass; //Describe the data structure of the Java class

class InstanceMirrorKlass; //Description java.lang.Class instance

class InstanceClassLoaderKlass; //Special InstanceKalss, do not add any fields

class InstanceRefKlass; //Describe the subclass of Java.lang.ref.Reference

class ArrayKlass; //Describe Java array information

class ObjectArrayKlass; //Describe the data structure of the reference type array in Java

class TypeArrayKlass; //Describe the data structure of the basic type array in Java

Among them, Klass is the top parent class of the klass family. ArrayKlass is the parent class of ObjArrayKlass and TypeArrayKlass.

It can be found that members of the oop family have a corresponding relationship with members of the klass family.

For example, instanceOopDesc ​​corresponds to InstanceKlass. objArrayOopDesc ​​corresponds to ObjeArrayKlass.

Let's take a look at the definition of oop's top-level parent class oopDesc:

class oopDesc {

friend class VMStructs;

private:

volatile markOop _mark;

union _metadata {

wideClassOop _class;

narrowOop _compressed_klass;

} _metadata;

// Fast access to barrier set. Must be initialized.

static BarrierSet* _bs;

}

oopDesc ​​contains two data members: mark and _metadata.

The markOoptype of mark object refers to the Mark Word mentioned above.

metadataIt is a union body, where klass is an ordinary pointer and _compressed_klassa compressed class pointer. These two are the metadata pointers in the object header. They all point to instanceKlass according to the corresponding relationship, and instanceKlass is used to describe metadata. instanceKlass inherits from klass, let's take a look at the definition of klass:

jint _layout_helper; //Comprehensive descriptor of object layout

Symbol* _name; //class name

oop _java_mirror; //The mirror class of the class

Klass* _super; // parent class

Klass* _subklass; //The first subclass

Klass* _next_sibling; //The next sibling node

jint _modifier_flags; //modifier flag

AccessFlags _access_flags; //Access authority identification

You can see that klass describes the metadata. Specifically, it is the equivalent C++ type description of the Java class in the Java virtual machine.

In this way, instanceKlass inherited from klass can also be used to describe metadata.

Knowing the oop-klass model, we can analyze how the JVM finds the corresponding object instance through the object reference in the stack frame.

4.3 The life cycle of Java objects in the virtual machine


After the Java object is loaded into the virtual machine by the class, the Java object has 7 stages in the Java virtual machine:

  1. Creation stage

The specific steps in the creation phase are:

(1) Allocate storage space for the object

(2) Construction object

(3) Initialize static members from superclass to subclass

(4) Recursively call the constructor of the superclass

at last

In fact, there are only so many knowledge points in Android development, and there are still so many things to ask in the interview. So there are no other tricks in the interview, it just depends on how well prepared you are for these knowledge points. So, when you go out for an interview, just check which stage you have reviewed.

For the 2019-2021 high-frequency interview questions of Tencent, Toutiao, Ali, Meituan, ByteDance and other companies shared above , the blogger also organized these technical points into videos and PDFs (actually it took a lot more than expected Energy), including knowledge context + many details , due to limited space, the above is only a part of it in the form of pictures.

Android learning PDF+learning video+interview document+knowledge point notes

[Android mind map (skill tree)]

Knowledge is not systematic? There is also a mental map of Android advanced learning sorted out here, for your reference.

[Android advanced architecture video learning resources]

High-frequency interview questions**, the blogger also organized these technical points into videos and PDFs (in fact, it took a lot more effort than expected), including knowledge context + many details , due to limited space, the above is only in the form of pictures Show you a part.

Android learning PDF+learning video+interview document+knowledge point notes

[Android mind map (skill tree)]

Knowledge is not systematic? There is also a mental map of Android advanced learning sorted out here, for your reference.

[External link image transfer...(img-h9b4jCTW-1644995678352)]

[Android advanced architecture video learning resources]

Guess you like

Origin blog.csdn.net/m0_66264630/article/details/122964239
Recommended