JVM is seldom used in our daily development process, but when we consider the architecture design and system-level process development, we have to consider the jvm memory model. JVM stipulates the memory application, allocation, and management strategies of java operation, especially in Performance tuning, system exception investigation is often used, so you need to understand JVM to build an efficient and stable system
Refer to the classic JVM memory model divided into five parts:
1、Method Area:
It mainly stores class loading information (class life cycle: loading , verification, preparation, analysis, initialization, use, unloading), constants, static variables, and JIT compiled class data. There are several characteristics of the method area: global sharing , Permanent (with the JVM life cycle, gc generally does not occur) , garbage collection mechanism is not allowed here, and expansion is not allowed, OutOfMemoryError will occur when the method area memory is not enough, personally did not use the adjustment method to memory
The common method area is to set the size. Currently, the meta space above JDK8 is commonly used . The constant pool size is set as follows, but it is not commonly used and has no actual combat experience.
-XX:MetaSpaceSize和-XX:MaxMetaspaceSize=5M
Before jdk7, set the size as follows
-XX:PermSize和-XX:MaxPermSize
2、Heap
Heap memory allocation is closely related to the operating efficiency of the system, and is also the main source of OOM. This memory stores instance objects of the class. Generally, the heap memory is expandable. The commonly used settings of the heap size are as follows
-Xms -Xmx
The heap is divided into several areas, the new generation eden and the old generation (the old generation before jdk7). The ratio of the two occupied heap space is specified by -XX:NewRatio=n . In addition, the commonly used online generation heap snapshot instructions are as follows:
jmap -dump:live,format=b,file=heap-dump.bin <pid>
Cenozoic
The Cenozoic is divided into Eden, from survivor (S0), and to survivor (S1). The ratio between them is generally 8:1:1. The several commonly used GC periods minor gc occurred in Eden, and young gc occurred in Eden, s0 or s1 of the entire new generation. The size of the entire area is specified by -Xmn, and the size is usually adjusted here.
Old age
Newly-built objects generally go into eden first, and minor gc generally occurs in the new generation. Newly-built large objects cannot be directly over-old when stored in the new generation. Major gc occurs in the old generation.
Some people may question this, but how does full gc happen? If you don’t have to think about it, of course, full gc occurs in the old generation. When the young generation object is not associated with the gc root, it has not been recycled and stored in the old generation after many garbage collections. Due to the major gc in the old generation, it cannot be recycled and the heap memory cannot be stored. Will lead to full gc in order to make room. The occurrence of full gc is a very serious problem, which directly causes the application to slow down or even stop.
The young gc occurs 15 times by default in the new generation. After 14 times, if it is not recycled, it will enter the old generation. The general process of the new generation and the old generation and OOM occurrence is as follows. We often set the occupation ratio of the new generation and the old generation, but actually set the young gc Frequency to achieve a certain effect.
Heap tuning has the following parameters. Generally, it is impossible to perfect the process. According to the CAP principle (consistency, availability, and partition tolerance), it can only be set according to the application's own situation
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heapdump.hprof | Set the address of the jvm heap exception snapshot |
-Xms -Xmx | Set the heap maximum and minimum |
-XX:MaxPermSize=n | Persistent generation size |
–XX:NewRatio=n | Set the occupation ratio of the new generation and the old generation |
-XX:SurvivorRatio | eden and survivor ratio |
-XX:MaxTenuringThreshold | young gc times, default 15 |
-XX:+UseParallelGC | Parallel collector |
-XX:+UseSerialGC | Serial collector |
-XX:+UseG1GC | Use G1 algorithm |
-XX:MaxGCPauseMillis | G1 maximum pause time, milliseconds |
-XX:+PrintGC | Print gc log |
-XX:+PrintGCDetails | Garbage collection data details |
-XX:+PrintGCTimeStamps | Recycling time can coexist |
-Xloggc:filepath | Record gc detailed log file |
Commonly used jvm heap debugging tools are:
arthas Alibaba integration tool
top command to find java process
jconsole remote or local debugging
jvisualvm visual monitoring
jstack -l pid >> filepath stack information
jmap -dump:live,format=b,file=heap-dump.bin <pid> 生成快照
jhat analysis map information
3. VM Stack
The concept of the stack everyone should think of the concept of stacking and popping. In fact, the method call process is the stacking and popping of stack frames. The main content of the virtual machine stack is local information, which is private to the thread, such as local variables and operations. Stacks, dynamic connections, method return addresses, etc. It is common here that the depth of the stack exceeds the limit, which is StackOverflowError. For example, we look at the following code:
package com.jvm;
public class MainTest {
public static void main(String[] args) throws InterruptedException {
try {
addStackLength();
} catch (Throwable e) {
System.out.println("stackLength=" + stackLength);
e.printStackTrace();
}
try {
stackLength = 0;
addStackLength();
} catch (Throwable e) {
System.out.println("stackLength=" + stackLength);
//e.printStackTrace();
}
}
private static int stackLength = 0;
public static void addStackLength() {
stackLength++;
MainTest.addStackLength();
}
}
The above code will output
stackLength=23366
java.lang.StackOverflowError
stackLength=62790
java.lang.StackOverflowError
You will find weird problems. The depth of each run above is not fixed. This is related to JIT. Please check JIT for details.
The above code method with javap -verbose filepath is as follows
public static void addStackLength();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=0, args_size=0 // 栈最大深度2 ,局部变量0 ,入参0
0: getstatic #9 // Field stackLength:I
3: iconst_1 // 常量值入栈1
4: iadd // ++
5: putstatic #9 // Field stackLength:I 设置变量值
8: invokestatic #2 // Method addStackLength:()V 调用静态方法V
11: return
LineNumberTable:
line 23: 0
line 24: 8
line 25: 11
static {};
descriptor: ()V
flags: ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: iconst_0
1: putstatic #9 // Field stackLength:I
4: return
LineNumberTable:
line 20: 0
}
It can be seen that each method call is the process of pushing and popping the virtual machine stack.
4. Local method stack
The local method stack is mainly related to the Native method service, here is not restricted by the JVM, you can read related materials independently!
5. Program counter
The program counter mainly deals with the CPU, recording the offset of the execution instruction of the virtual machine and the line number commander, etc. There is no concept of memory overflow!
to sum up
The virtual machine usage scenario is wrong, but it is very valuable and meaningful. When individuals build a small and medium-sized bank system, they use simple tools such as heap memory optimization and troubleshooting. And the personal writing ability is not very good, if there are any shortcomings, I would like to show you more!