JVM(9)--JVM common parameter settings and OOM exceptions

One, JVM parameter type

There are 3 types of JVM parameters:

  • Standard parameter
  • X parameter
  • XX parameter

1.1 Standard parameters

The standard parameters remain basically unchanged in each version of the JVM. Relatively stable, for example:

  • -help
  • -server -client
  • -version -showversion
  • -cp -classpath

1.2 X parameters

  • Xint Interpretation and Execution
  • -Xcomp: compile local code the first time you use it
  • -Xmixed: Mixed mode, JVM decides whether to compile local code by itself

1.3 XX parameters

The xx parameter is the main parameter that we need to set for tuning. The XX parameter is divided into two categories: Boolean type and kv setting type

  • Boolean type: Format: -XX:[±] means to enable or disable the name attribute. The + sign indicates that the parameter is enabled, and the-sign indicates that the parameter is disabled.

  • KV key-value pair type parameters

Format: -XX:= indicates that the value of the name attribute is value, mainly in the form of key and value.

2. Common parameters

2.1 View default values

2.1.1 jinfo

The function of jinfo is to view and adjust various parameters of the virtual machine in real time. For example: need to view the size of the meta space in the jvm

jinfo -flag MetaspaceSize 15264(进程号)

image-20201225192147441

2.1.2 Using commands
  • java -XX:+PrintFlagsInitial View the initial default value

image-20201225192335854

  • java -XX:+PrintFlagsInitial View modification updates

image-20201225192816621

Looking at the output, you will find that some of them are :=, these are the modified values

  • = Has not been modified
  • := Modified

2.2 JVM commonly used parameters

2.2.1 -Xms

-Xms is equivalent to -XX:InitialHeapSize, the size of the initialized heap space

image-20201225195339698

The default heap space size is 1/64 of the computer memory, my computer has 20g of memory, so the initial heap space size is 320mb

Example of use: -Xms10m

image-20201225195831573

2.2.2 -Xmx

-Xmx is equivalent to -XX:MaxHeapSize, the maximum heap space size

image-20201225200241874

The default maximum heap space size is 1/4 of the computer memory, so the maximum heap space size is 5120mb

Example of use: -Xmx10m

image-20201225200607096

2.2.3 -Xss

Set the heap memory size, equivalent to -XX:ThreadStackSize

The default value is generally 512k~1024k

image-20201226094317425

Here -XX:ThreadStackSize=0 is 0, not that the memory size of the virtual machine stack is 0, but the default value of jvm

Example of use: -Xss1024k

image-20201226094544778

2.3.4 -Xmn

Set the size of the young generation, the size of the young generation is generally 1/3 of the heap, and this parameter is generally unchanged

2.3.5 -XX:MetaspaceSize

-XX:MetaspaceSize is to set the size of the metaspace, the metaspace is not on the virtual machine, but the local memory is used, so by default, the size of the metaspace is limited by the local memory

View the initial value of the meta space:

image-20201226095643692

So, increase the MetaspaceSize

2.3.6 -XX:+PrintGCDetails

Print GC information, the main focus is the printed log information

-XX_+PrintGCDetails print informationimage-20201227123936029

The log information after GC printing is mainly divided by ->, the front is before the GC, the back is after the GC, and the total size in the brackets

2.3.7 -XX:SurvivorRatio

Set the ratio of Eden area and Survivor area (From Survival Area or To Survival Area) in the Cenozoic. The default value is 8

image-20201227130739072

Use XX: SurvivorRatio to set this ratio

2.3.8 -XX:NewRatio

Set the ratio of the young generation to the old generation, the default value is 2

image-20201227131113791

Use -XX:NewRatio to set this ratio size

2.3.9 -XX:MaxTenuringThreshold

Control how many times the young generation needs to go through GC promotion to the maximum threshold in the old generation, the default value is 15

image-20201227131253986

Note that setting this value must be within 0-15. The picture below shows the error that I want to set to 20 and then report an error. The reason is that the maximum value for controlling this object to be promoted to the old age is in the object header, and 2 is used Bits so the maximum value is 15

image-20201227131403346

2.3.10 Summary

Take a picture to summarize the above parameters

JVM common parameters

Three, common exceptions

OOM is OutOfMemoyError. First of all, it is clear that OOM is an error, which is an error of insufficient jvm memory

image-20201229203844943

In the Java virtual machine specification, it is clearly stipulated that all runtime data areas other than the program counter may emit OOM exceptions (of course, we are accustomed to verbally call them exceptions)

3.1 StackOverflowError

StackOverflowError is a stack overflow exception. If the depth of the stack requested by the thread is greater than the depth allowed by the virtual machine, a StackOverflowError will be thrown, for example:

public static void main(String[] args) {
    
    
    test();
}
public static void test(){
    
    
    test();	//不断递归调用自己
}

image-20201229204642034

3.2 OOM:Java heap space

/**
     * -Xms5m -Xmx5m
     * @param args
     */
public static void main(String[] args) {
    
    
    Byte[] bytes = new Byte[10 * 1024 * 1024];
}

image-20201229204947624

The solution is to adjust the size of the heap

3.3 OOM:GC overhead limit exceeded

When the Java process takes more than 98% of the time to perform GC, but only recovered less than 2% of the memory, and the action is repeated five times in a row, it will throw java.lang.OutOfMemoryError:GC overhead limit exceededan error. Simply put, the application has basically exhausted all available memory, and the GC cannot reclaim it. This should throw an exception. If you don’t throw an exception, it will cause the 2% of the memory cleaned by the GC to be filled up immediately, causing the GC to execute again, and then fill it up again, leading to a vicious circle

/**
     * -Xms10m -Xmx10m -XX:+PrintGCDetails -XX:MaxDirectMemorySize=5m
     * @param args
     */
public static void main(String[] args) {
    
    
    List<String> list = new ArrayList<>();
    int i = 0;
    try {
    
    
        while(true){
    
    
            list.add(String.valueOf(i++).intern());
        }
    }catch (Throwable e){
    
    
        e.printStackTrace();
    }finally {
    
    
        System.out.println(i);
    }

}

image-20201229210310101

3.4 OOM:Direct buffer memory

Java allows applications to directly access off-heap memory through Direct ByteBuffer, and many high-performance programs implement high-speed IO through Direct ByteBuffer combined with Memory Mapped File. Javad's NIO program uses ByteBuffer to read or write data. ByteBuffer has two ways:

  • allocate: Allocate JVM heap memory, which belongs to the recovery range of GC, but the speed is slow due to copying from local memory
  • allocateDirect: directly allocates off-heap memory, that is, local memory, with faster transmission speed
/**
     * -XX:MaxDirectMemorySize=5m
     * @param args
     */
public static void main(String[] args) {
    
    
    ByteBuffer.allocateDirect(6 * 1024 * 1024);
}

image-20201229211855036

3.5 OOM:Unable to create new native thread

JVM requests the operating system to create a native thread if it fails, it will throw it out Unable to create new nativethread. Common reasons include the following types:

1. The number of threads exceeds the ulimit limit of the maximum number of threads of the operating system;

2. The number of threads exceeds kernel.pid_max (can only be restarted);

3. Insufficient native memory;

public class UnableCreateNewThreadDemo {
    
    
    public static void main(String[] args) {
    
    
        int i = 0;
        try {
    
    
            for (;;i++) {
    
    
                new Thread(() -> {
    
    
                    //防止进程醒来
                    try {
    
     TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);} catch (InterruptedException e) {
    
    e.printStackTrace();}
                }).start();
            }
        }catch (Throwable e){
    
    
            e.printStackTrace();
        }finally {
    
    
            System.out.println(i);
        }
    }
}

Run the above java program on Centos7. Note: You need to use an ordinary user to run this program. Using root may cause the process to be created all the time and cause the machine to get stuck.

image-20201230212644363

It was found that 4085 processes were created, and the Unable to create new native thread exception was reported.

There are two solutions to the above problems:

  • Increase the maximum number of processes allowed by the operating system, take Centos7 as an example
[test@hadoop101 ~]$ ulimit -u	#查看当前用户所能创建的最大进程数

image-20201230213004120

It can be found that, in fact, it is somewhat different from the above 4085, and there will be some daemon processes when the java program is running.

The maximum number of processes that can be created by ordinary users can be increased by modifying the configuration file /etc/security/limits.d/20-nproc.conf

image-20201230214510271

It can also be seen from the above that the maximum number of processes that ordinary users have is 4096, then this value can be modified to increase the number of processes

  • The second method is to reduce unnecessary processes

3.6 OOM:Metaspace

The meta space stores the structural information of the class. The meta space is not in the JVM, but in the local memory, but the default size of the meta space is only close to about 21mb

image-20201230220036713

Therefore, there may be an OOM situation, look at the following code:

public class MetaspaceDemo extends ClassLoader{
    
    
    /**
     *jdk1.8 环境配置如下参数
     * -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
     * @param args
     */
    public static void main(String[] args) {
    
    
        int j = 0;
        try {
    
    
            MetaspaceDemo test = new MetaspaceDemo();
            for (int i = 0; i < 10000; i++) {
    
    
                //创建ClassWriter对象,用于生成类的二进制字节码
                ClassWriter classWriter = new ClassWriter(0);
                //指明版本号,修饰符,类名,包名,父类,接口
                classWriter.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, "Class" + i, null, "java/lang/Object", null);
                //返回byte[]
                byte[] code = classWriter.toByteArray();
                //类的加载
                test.defineClass("Class" + i, code, 0, code.length);//Class对象
                j++;
            }
        } finally {
    
    
            System.out.println(j);
        }
    }
}

Guess you like

Origin blog.csdn.net/weixin_44706647/article/details/115193964