preface

Just last week I wrote about my delightful discussion with My sister about the JVM, and it was diss.

By the way, haven’t read the previous article little lovely please move here first: that day I and little sister pulled a long time of JVM

Egg brother: about JVM little elder sister’s understanding quite good, why don’t you sort out complete!

I: because the article word number is limited, condense is essence ~

Egg brother: lazy is lazy, but also lazy said so fresh and refined ~ (and throw me a white eye)

I: hee hee ~ that I again complement complement…

Egg brother didn’t talk to me again, threw me a file, began to write code.

After a while, two lines of messages from Dange popped up on wechat: after reading your article, I made some simple additions around the following points:

  1. A shift in the JVM memory region
  2. Java code runs the procedure
  3. Run time stack frame structure
  4. JVM heap memory allocation method
  5. How does the JVM locate access to objects?

The body of the

A shift in the JVM memory region

As we saw in the previous article, the method area mainly stores information about the class and is shared by all threads, implementing the method area as a permanent generation.

But there are fundamental differences between method regions and permanent generations. The method area is the specification of the JVM, and persistent generation is an implementation of the JVM specification, and only HotSpot has persistent generation, and there is no such thing as persistent generation for other types of virtual machines, such as JRockit (Oracle), J9 (IBM).

In this article, we will use HotSpot as an example. Let’s take a look at the JVM runtime areas of JDK1.6 and earlier, as shown below:

However, after JDK1.8, the permanent generation was removed and replaced with a meta-space. The specific evolution process is maozi:

But why were permanent generations removed after JDK1.8 and replaced with meta-spaces? What’s the good of that?

Before we discuss this, we need to understand the concept of metacarspace:

Meta-space: Simply an area of space that stores metadata information about a class. The meta-space is not in the virtual machine, but uses local memory.

So what is metadata?

Metadata, the data about the data or the data that describes the data or the information.

Sound abstract??

Let’s just say we can think of metadata simply as the smallest unit of data. Metadata can describe its elements or attributes for data, such as name, size, data type, etc., or its structures such as length, fields, data columns, etc., or its related data, where it is located, how it is related, owner, etc.

Now that you understand the concepts of meta-space and metadata, let’s talk about its benefits.

In essence, meta-spaces are similar to permanent generations in that they are implementations of method areas in the JVM specification. As we know, it is difficult to determine the size of class and method information, so it is difficult to specify the size of permanent generation. If it is too small, it is easy to overflow permanent generation, while if it is too large, it is easy to overflow old generation. The meta-space is not in the virtual machine, but uses local memory. Therefore, by default, the size of the meta-space is not controlled by the JVM and GC is no longer performed, it is only limited by local memory, so no OOM exceptions occur.

Java code runs the procedure

The entire running process of Java code can be divided into compilation phase and loading phase.

Let’s take a look at what happens to Java source code at compile time:

1. Compilation phase

Java source code generates bytecode through a series of execution processes such as lexical parsing, syntactic parsing, and semantic parsing.

Very abstract, right? What is lexical, what is syntactic, what is semantic?? Don’t worry, let’s explain one by one:

Lexical parsing: Information such as words, operators, and control characters is separated by Spaces and sent to the grammar parser as token information flow.

Syntax parsing: The token information stream obtained from lexical parsing is assembled into a syntax tree according to Java syntax rules.

Semantic parsing: Check whether the keyword is used properly, whether the type matches, whether the scope is correct, etc.

With that in mind, let’s take a look at what happens during the load phase:

2. Loading phase

Loading stage The class loader loads the bytecode into the JVM after a series of actions such as Load stage, Link stage, and Init stage. There are three execution modes: interpreted execution, JIT compiled execution, and JIT compiled and interpreted execution.

Blah blah blah…? What Load phase? What Link phase? What Init phase? Can you be more specific??

To be specific:

The Load phase reads the Class file, generates a binary stream, converts it to a specific data structure, initially verifies whether it is a Java Class file or whether the file is damaged, constant pool, file length, parent Class, etc., and then creates the corresponding java.lang.class instance.

The Link phase consists of three steps: verification, preparation, and parsing. Validation is more detailed verification, such as final compliance, type correctness, static variables are reasonable, etc. The preparation phase allocates memory for static variables and sets default values. Parsing classes and methods ensures correct references between classes and completes the layout of the memory structure.

The Init phase executes the clinit method, the class constructor, and if the assignment is done through a static method of another class, the other class is immediately parsed and the assignment is returned in the virtual machine.

Its entire process is shown below:

Run time stack frame structure

The runtime stack frame structure looks like this:

  1. The internal structure of the virtual machine stack is the stack frame. Each method will create a stack frame when executing, which is used to store information such as local variable table, operand stack, dynamic link, method return address, etc.

  2. The local variable table is used to complete the process of passing method parameters and the list of local variables. If an instance method is used, the default Slot for each 0 bit index in the local variable table is used to pass a reference to the instance of the object that the method belongs to.

  3. During method execution, various bytecode points to the operand stack to write and extract values;

  4. A method calls another method by dynamically linking it to a constant pool to query a method’s reference.

  5. Method return address, that is, before a method exits, it must return to the location where the method was called before the program can continue execution.

  6. The process of a method calling another method, i.e. the process of a stack frame being pushed into and out of the virtual machine.

Finally, methods are pushed in the same order as methods are called in the virtual machine. Methods pushed first are removed from the virtual machine, and methods pushed last are removed first.

JVM heap memory allocation method

At present, the main memory allocation methods are pointer collision method and free list method.

Pointer collision: Assume that the memory in the heap is absolutely neat, all used memory is stored on one side, unused memory is put on the other side, and there is a pointer in the middle as a critical point. If a new object is created, the pointer is moved to the unallocated memory by the same distance as the object memory. This is called pointer collision. As shown below:

Free list method: It is based on the marker clearing algorithm, memory is divided into grid areas, memory allocation is not orderly, that is, used and unused memory randomly distributed. The JVM maintains a record of which memory is available for allocation. When an object needs to be allocated memory, the JVM finds a large enough memory area to allocate to the object and updates the record table. This method of allocating memory is called the free list method. As shown below:

How does the JVM locate access to objects?

We naturally create objects for later use, and Java programs manipulate specific objects on the heap using reference data on the stack.

However, the Java Virtual Machine Specification only stipulates that the reference type is a reference to an object, and does not define how the reference should locate and access the specific location of the object in the heap. Therefore, the object access mode is also determined by the virtual machine.

However, the current mainstream access methods have two ways: handle and direct pointer.

Pointer: Points to an object and represents the starting address of an object in memory.

Handle: A pointer to a pointer that maintains a pointer to an object. Instead of pointing directly to an object, the handle points to a pointer to the object (the handle does not change, pointing to a fixed memory address), which in turn points to the object’s real memory address.

Knowing the concepts of Pointers and handles, let’s take a look at how they position access to objects.

1. Handle access

A block of memory is allocated in the Java heap as a handle pool, and the reference stores the handle address of the object. The handle contains the specific address information of object instance data and object type data respectively, as shown in the figure below:

The advantage is that the reference is stored in a stable handle address before the object is moved. For example, when moving objects is a common behavior during garbage collection, only the instance data pointer in the handle is changed, and the reference itself does not need to be modified.

2. Direct pointer

If direct pointer access is used, the direct stored in the reference is the address of the object, then the layout inside the Java heap object must consider how to place information about accessing type data.

Faster, saving the time cost of a pointer location. Because objects are accessed very frequently in Java, this kind of overhead can add up to significant execution costs. This is the approach used in HotSpot.

The last

Thank you very much for reading this, JVM content is so complex that it is impossible to analyze everything in just two articles. In these two articles, we have compiled some of the most common interview questions. The questions are relatively common, but they are also the most frequently asked interview questions.

The more routine we are, the more we have to comprehend, understand, and master. But these relatively regular knowledge points you say you do not know, so I can say what ~ self. Oh no, follow me

If there are any mistakes in this article, please comment, thank you very much!

If you enjoyed this article, give it a thumbs up

Welcome to follow my wechat public account [xiaoxiaozi], we discuss code and life together.

Article Reference:

  1. In-depth Understanding of the Java Virtual Machine
  2. https://blog.csdn.net/u011531613/article/details/62971713
  3. https://blog.csdn.net/qq_38905818/article/details/10458235
  4. https://www.zhihu.com/topic/19566470/hot
  5. https://blog.csdn.net/u010588262/article/details/81365547