Parsing the overall structure of the JVM

Introduction to the overall structure

The JVM is divided into:

  • Stack –
  • Methods area
  • The heap
  • Local method stack
  • Program counter
Stack Stack

The stack is an important part of the JVM. Each new thread is allocated a memory on the stack. The thread contains stack frames and program counters. In addition, the memory size of the thread stack determines the number of threads. When the memory size of the thread stack is set to be larger, the number of concurrent threads will be smaller, and the inverse will be larger. StackOverflowError StackOverflowError StackOverflowError Stack overflow

public class StackOverflowTest { static int count = 0; static void redo() { count++; redo(); } public static void main(String[] args) { try { redo(); } catch (Throwable t) { t.printStackTrace(); System.out.println(count); }}} running results: Java. Lang. StackOverflowErrorCopy the code

-xss 256KB(default: 1M) Sets the stack size. The stack size affects the count count. The larger the -xss value, the greater the count count, and vice versa.

Stack frame structure
  1. Local variable table: It is mainly used to save declared local variables and method parameter information. The local variable table acts on the current method. When the method is executed, the local variable table will also be deleted to release memory. The other part of the local variable list that holds information is called a slot
type Number of slot
byte 1
short 1
int 1
long 2
float 1
double 2
boolean 1
char 1

Operand stack: As the name suggests, the operand stack is essentially a stack, push, and out of the stack. For example, a+ B is executed. First, a and B in the local variable table are pushed into the stack, followed by the addition operation, and finally out of the stack.

Dynamic link: it is completed during the program running to replace symbolic references with direct references called dynamic link, since there are dynamic links then there are static links, some symbolic references in the class loading phase (parsing) when converted to direct references, this transformation into static links.

Method return address: Returns where the method was called after the method exits (normal execution/exception return).

The stack structure

Program Counter Register

A program counter, also known as a PC register, is a very important structure in the JVM. It is thread private, one for each thread. It is used to hold the address of the next instruction to be executed.

Native Method Stack

The local method stack is mainly used to execute native methods and hold the address that native methods enter into the region, so the local method stack is also a thread-private memory region.

Method Area(Meta Space)

Shared by all threads. The method area contains all class and static variables, class method codes, variable names, method names, access permissions, return values, and often the constant pool and run-time constant pool.

Heap Heap

The heap is a very important area that manages almost (not all) objects, and it is in this area that we often say the main area of garbage collection takes place. The heap is divided into young and Old, the Cenozoic is divided into Eden and survivor, and the survivor is divided into From and To. There are two main types of GC: minorGC (Young GC) and Full GC. JVM tuning is based on code to adjust JVM parameters to reduce the number of Full GCS.

Reactor structure diagram

Escape analysis

So the first thing you hear the most is that new comes out and the object is in the heap, but in the previous article, it said almost the object is in the heap, so why almost, because some objects are in the stack, isn’t that weird? Let’s look at the next piece of code.

Public Person test1() {Person Person = new Person(); person.setId(1); return person; Public void test2() {User person = new person(); person.setId(1); }Copy the code

The personr object in test2, when the method ends, is an invalid object and will not be referenced anywhere else. For such an object, The JVM allocates the stack memory to be reclaimed along with the stack memory at the end of the method, reducing heap memory reclamation. The JVM can optimize the location of the object’s memory allocation by enabling escape analysis (-xx :+DoEscapeAnalysis). After JDK7, escape analysis is enabled by default. If you want to disable it, use the parameter (-xx: -doescapeAnalysis).

Object memory allocation

Object memory allocation flowchart

Object allocation on the stack

In this case, the JVM can optimize the location of the object’s memory allocation by enabling escape analysis (-xx :+DoEscapeAnalysis). In this case, the JVM can optimize the location of the object’s memory allocation by enabling escape analysis (-xx :+DoEscapeAnalysis). To turn it off, use the parameter (-xx: -doEscapeAnalysis)

Scalar substitution: When escape analysis determines that the object is not externally accessed and that the object can be further decomposed, the JVM does not create the object. Instead, the member variables of the object are decomposed into several variables that are used by the method. These substitute member variables allocate space on the stack frame or register. This way you don’t run out of object memory because you don’t have a large contiguous space.

Enable scalar substitution arguments (-xx :+EliminateAllocations) and by default after JDK7.

Scalar and aggregate quantity: scalar is the quantity that cannot be further decomposed, also can be said to be atomic weight, which cannot be decomposed again, and the basic data type of JAVA is scalar (such as: int, long and other basic data types and reference type, etc.), the opposite of scalar is the quantity that can be further decomposed, and such quantity is called aggregate quantity. In JAVA, objects are aggregates that can be further decomposed

Conclusion: Stack allocation relies on escape analysis and scalar substitution

Objects are allocated in Eden

When an object is first created, it is allocated in Eden, and when Eden is full, a minor GC is triggered. Perhaps 99% of the objects will be garbage collected, and the remaining remaining objects will be moved to survivor. The next time Eden is full, a minor GC will be triggered again. Collect the Eden and survivor garbage objects, and move the remaining surviving objects to another empty survivor area at once. Since the new generation of objects has short health and short lifetime, the JVM’s default ratio of 8:1:1 is a very reasonable ratio. Therefore, we should make the Eden zone as large as possible and the survivor zone as large as possible.

The JVM has this parameter by default ** -xx :+UseAdaptiveSizePolicy**(enabled by default), which causes the 8:1:1 ratio to change automatically.

If you do not want this ratio to change, you can set the parameter ** -xx: -useadaptivesizePolicy **

What happens when Eden runs out of memory?

The virtual machine initiates a Minor GC if there is not enough space in Eden to allocate memory for the new object. During the GC, the virtual machine discovers that the new object cannot be stored in Survior space, so it has to move the new generation of objects to the old generation. In the old days, there is enough space to hold new objects, so Full GC does not occur. After a Minor GC is performed, memory will still be allocated in Eden, if any of the objects to be allocated can exist in Eden.

Big objects go straight into the old age

A large object is an object that requires a large amount of contiguous memory space (e.g. strings, arrays). JVM parameters – XX: PretenureSizeThreshold can set the size of a large object, if the object is more than set size goes straight to the old age, not the young generation, this parameter only in Serial and ParNew under the two collector (later speak about collector).

Such as setting up the JVM parameters: – XX: PretenureSizeThreshold = 1000000 (byte) – XX: + UseSerialGC, perform the procedure will find large objects with large object directly into old age

The benefit?

To avoid inefficient replication operations when allocating memory for large objects.

Long-lived objects will enter the old age

Since virtual machines manage memory in generational collections, it is important to recognize which objects belong in the new generation and which belong in the old. To do this, the virtual machine gives each object an object Age counter. If the object survives Eden’s birth and the first Minor GC, and can be accommodated by Survivor, it will be moved to the Survivor space with the object age set to 1. The age of an object increases by one year for each MinorGC it survived in Survivor, and when it reaches a certain age (15 years by default, 6 years for CMS collectors, and slightly different for different garbage collectors), it is promoted to the old age. The object is promoted to the old age

Is the age threshold.

JVM parameter Settings -xx :MaxTenuringThreshold.

Dynamic age judgment of objects

If the total size of a batch of objects in the current Survivor area is greater than the memory size of the Survivor area

50%(-xx :TargetSurvivorRatio can be specified), then the objects whose age is greater than or equal to the maximum value in this batch of objects can enter the old age directly.

For example, there is now a group of objects in the Survivor area, and the sum of multiple age objects with age 1+ age 2+ age N exceeds 50% of the Survivor area

Put all objects with age n and above into the old age. The rule is to hope that those who might be long-term survivors will enter the old age as soon as possible. Object dynamic year

The aging mechanism is usually triggered after the minor GC.

Old space allocation guarantee mechanism

Before each minor GC in the young generation, the JVM will calculate the remaining free space in the old generation if the available space is less than the sum of all the objects in the young generation (including garbage objects). If this parameter is set, it will see if the size of the available memory in the old age is greater than the average size of objects that entered the old age after each previous minor GC. If the result of the previous step is less than or the previous parameter is not set, then a Full GC will be triggered, collecting both the old generation and the young generation. If there is still not enough space for the new object, then “OOM” will occur. If the remaining objects that need to be moved to the old age after the minor GC are still larger than the available space in the old age, then full GC will also be triggered. If there is still no room for the remaining objects after the Minor GC, then “OOM” will also occur.

conclusion

  1. The runtime data area consists mainly of heap, stack, program counter, method area, and local method stack

  2. Thread private areas: thread stack, program counter, local method stack, thread shared areas: heap, method area.

  3. The heap is subdivided into new generation (Eden, Survivor (From, To), default ratio 8:1:1) and old generation

  4. Objects are not all in the heap, after the escape occurs the eligible objects in the stack

  5. The overall structure of the JVM is shown below

END