preface

Dear readers, I am writing a series of articles on Java multithreading. Strictly speaking, the knowledge of the JVM memory model does not belong to the Java multithreading category, but in the process of discussing multithreading, related concepts will be involved. Considering that it is a frequent guest, it is a separate article for knowledge combing.

Under all kinds of intentional or unintentional rendering, the environment has been filled with anxiety, I do notI don’t think it’s really necessary for a proper interviewAfter all, very few jobs are in developing JVMS. This article will do its best to do soEasy to rememberTo help youOvercoming anxiety!

In this article, we review and master the key knowledge of the JVM memory model and JVM thread model in condensed graphs, supported by text.

According to my limited knowledge,Please point out any errors in the comments section

Understand the series and overview: Java Multithreading series

Let’s start with a more complete picture:

Author press: Image derived from template of yitu icon

After adding the GC section on the right side, it is more complete. In today’s article, the class loading section is omitted, and the GC section is omitted.

The author presses: the reader friend still should understand these two parts, if the interview encounters, can follow the picture to expand the answer

In the figureJava stackAlso known as theJava virtual machine stackThe virtual machine stackThe JVM stackAnd so on;The local stackLocal method stack

JVM memory model

From the figure above, we strip out the runtime data area to form the following image, the JVM memory model (memory area) :

In JVM1.8, in the figureMethods areaMetadata area

In the context of multi-threading, we should:

  • The heap and method areas are shared by threads
  • The virtual machine stack, local method stack, and program counter are thread isolated

Let’s expand on the roles of these five regions.

Bounded by the Java Virtual Machine specification, implementations are not discussed

Method area (JVM1.8 is metadata area)

The function of the Method area is to store the type information, Field information, Method information, constants, static variables, and the code cache after the compiler compiles the virtual machine

Note that OutOfMemoryError is thrown when memory cannot be allocated

A pool of runtime constants exists in the method area, where literals, symbolic references, and so on are stored.

In the evolution of Hotspot:

  • Java6 and before: method areas have persistent generations that hold static variables
  • Java7: de-perpetuating work is carried out, although static constant pools, such as string constant pools, have been moved to the heap
  • Java8: Remove permanent generation, type information, Field information, Method information stored in metadata area; String constant pool, static variables stored in the heap area

Author according to: different virtual machine implementation details I have not studied, interested readers can study, if there is a reliable article hope to share

The virtual machine stack

Information about each method call is kept in the virtual machine stack.

When each Java thread is created, the corresponding virtual machine stack is created, and each method call pushes a stack frame onto the stack. The diagram below:

And the stack frame contains:

  • Local variable table: save function(Method)Local variable of
  • Operand stack: Holds the results of the calculation, namely temporary variables
  • Dynamic linking: Points to a pool of runtime constants in the method area. In bytecodeMethod call instructionRefers to a method in a constant poolSymbolic referenceAs a parameter.
  • Method return address

Local method stack

Functionally similar to the virtual stack, it manages some of the execution details of native methods, whereas the virtual stack manages the execution details of Java methods.

Program counter

The program counter records the bytecode line number executed by the thread, null if the current thread is running native methods. Also known as PC registers

When the bytecode interpreter is working, it selects bytecode instructions to be executed by the next hop by changing the value of the counter. Branch, loop, jump, exception handling, thread recovery and other basic functions need to be completed by the counter.

Multithreaded implementation of Java virtual machines: by switching and allocating processor execution time in turn

So, at any given point in time, a processor will only process instructions in one thread. To properly handle task recovery after a thread switch, each thread has its own program counter

The heap

The heap provides memory for class instances and arrays, which can be divided as follows:

  • The new generationIt can also be called the young Generation or New Generation
    • Eden area
    • Survivor areaThere is mutual movement in S0 and S1, and from and to in some articles refer to the logical relationship on movement
      • S0
      • S1
  • The old sOld Generation

As shown below:

Partitioning and object creation are related to GC,

  • The newly generated object is in the Eden area
  • After the Minor GC is triggered, objects that “survived” are moved to S0
  • After the Minor GC is triggered again, the surviving objects in S0 and Eden are moved to S1 and S0 is emptied
  • Automatically increments the counter each time it is moved beyond the default value(I remember 16)If there is not enough memory allocated in Eden, the memory will be allocated in the old age
  • The old days relied on the Major GC

A small summary

After summarizing the knowledge points above, we can get a new picture:

The image comes from the graph template, again without drawing 😂

JVM thread model

A Java thread can be implemented in one of three ways:

  • Implemented using kernel threads
  • Implemented using user threads
  • Use a mix of user threads and lightweight processes

There is no thread implementation specification for the JVM, but the specific JVM implementation needs to be combined. Let’s explore this briefly

Kernel thread model

Kernel Thread model: it completely relies on the kernel-level Thread (KLT) provided by the operating system Kernel to achieve multithreading. In this way: thread switching scheduling is completed by the system kernel.

In general, programs do not use kernel threads directly, but instead use an advanced interface known as light-weight processes (LWP).

Image from Internet

The kernel thread of the system is used by LWP in the user process. Because of its one-to-one relationship, it is also called one-to-one model

Since the user thread corresponds to LWP one by one, and LWP is an independent scheduling unit, the execution of the whole process will not be affected if a CERTAIN LWP is blocked in the process of user process call or system call.

However, LWP relies on Kernel thread, so thread operation needs to rely on system call, which costs a lot and requires switching back and forth between User Mode and Kernel Mode. Moreover, each LWP requires the support of a kernel thread, so LWP consumes certain kernel resources, so a system can only support a small amount of limited LWP.

User thread model

Excluding the kernel Thread, the JVM platform can also implement User Thread UT, which is completely created, scheduled and destroyed by itself.

Different from the kernel thread model, the scheduling of threads at this time no longer depends on the kernel, rarely occupies the kernel resources, and is basically limited to the user state, so it can break through the limit of quantity and reduce the loss of thread switching.

This might seem like a nice thing to do, but it’s hard to take advantage of multicore cpus, and if a system call is interrupted, other threads are interrupted.

This many-to-one model is less practical.

Hybrid model

Also known as the many-to-many model, this approach takes full advantage of the above two approaches.

In this model, both UT and LWP exist.

Creating and switching threads (UT) is still cheap and can have a large number of threads; At the same time, LWP is used as a bridge from UT to KLT (kernel thread) to enjoy the thread scheduling and CPU mapping of the system kernel, and the part of self-implementation of system call is spared. When making system call, the probability of blocking the whole process is lower than that of user thread model.

Afterword.

Another water article, I believe that readers have basically remembered these contents, can be happy to chew the fat. We hope the epidemic will end soon.