Vernacular brings you to know JVM

Time:2021-2-27

preface

If there are problems in the use of words or understanding, please point out. The purpose of this article is to mention and not to study deeply, but to throw out all the knowledge points as efficiently as possible

1、 Introduction of JVM

JVM is the abbreviation of Java virtual machine, it is a fictitious computer, a specification. All kinds of computer functions are realized by simulation on the actual computer···

Well, in fact, leaving aside such a professional sentence, we know that the JVM is actually similar to a small computer running in windows or Linux operating system environment. It directly interacts with the operating system, but not with the hardware. The operating system can help us complete the work of interacting with the hardware.

Vernacular brings you to know JVM

1.1 how java files are run

For example, we have now written one HelloWorld.java OK, this one HelloWorld.java Apart from everything, is it similar to a text file, except that the text file is written in English with certain indentation.

What about oursJVMIt doesn’t recognize text files, so it needs acompileAnd make it a binary that it can readHelloWorld.class

① Class loader

IfJVMWant to do this.classFile, we need to put it into aClass loaderIt’s like a porter, it’s going to take all of them.classAll the files are moved into the JVM.

Vernacular brings you to know JVM

② Method area

Method areaIt is used to store data similar to metadata information, such as class information, constants, static variables, compiled code, etc

The class loader will move the. Class file to this block first

③ Heap

heapMainly put some stored data, such as object instance, array, etc., which belong to the same method areaThread sharing area. That is to say, they are allThread unsafeOf

④ Stack

StackThis is our code run space. Every method we write is put in theStackIt runs inside.

We’ve heard of local stack or local method interface, but we won’t deal with them. They work in C, which has nothing to do with Java.

⑤ Program counter

The main task is to complete a load, which is similar to a pointer to the next line of code we need to execute. It’s the same as the stackThread exclusiveIn other words, each thread will have its own corresponding area, and there will be no concurrency and multithreading problems.

Vernacular brings you to know JVM

Summary

  1. Java file becomes. Class bytecode file after compiling
  2. Bytecode files are transported to the JVM virtual machine through class loader
  3. The main five blocks of virtual machine: method area and heap are shared by threads, which have thread safety problems. Stack and local method stack and counter are exclusive areas, and there is no thread safety problem. The tuning of JVM is mainly around heap and stack

1.2 simple code examples

A simple student class

Vernacular brings you to know JVM

A main method

Vernacular brings you to know JVM

The steps to execute the main method are as follows:

  1. Compile well App.java Get after App.class After that, execute App.class , the system will start a JVM process and find a path named App.class This process is called app class loading
  2. The JVM finds the main program entry of the app and executes the main method
  3. The first statement in the main is student student = new student (“tellurdream”), which is to let the JVM create a student object, but there is no student class information in the method area at this time, so the JVM immediately loads the student class and puts the student class information into the method area
  4. After loading the Student class, JVM allocates memory for a new Student instance in the heap, and then calls the constructor to initialize the Student instance, which is held by the Student instance.Type information that points to the student class in the method areaReference to
  5. implement student.sayName (), the JVM finds the student object according to the reference of the student, and then locates it to the method table of the type information of the student class in the method area according to the reference held by the student object to obtain the bytecode address of sayname().
  6. Execute sayname ()

In fact, you don’t need to worry too much. You just need to know that when the object instance is initialized, you will go to the method area to find the class information, and then go to the stack to run the method. Find the method in the method table.

2、 Introduction of class loader

It was also mentioned before that it is responsible for loading. Class files. They have a specific file label at the beginning of the file. It loads the bytecode content of the class file into memory, and converts these contents into the runtime data structure in the method area. Classloader is only responsible for loading class files, and whether it can run or not is determined by the execution engine

Process of type 2.1 loader

There are seven steps from class loading to memory release: loading, verifying, preparing, parsing, initializing, using and unloading. amongThe three parts of verification, preparation and resolution are collectively referred to as connection

2.1.1 loading

  1. Load the class file into memory
  2. Convert the static data structure into the runtime data structure in the method area
  3. Generate a file in the heap that represents this class java.lang.Class Object as the entry of data access

2.1.2 connection

  1. Verification: to ensure that the loaded class conforms to the JVM specification and security, and that the methods of the verified class will not do any harm to the virtual machine when running, is actually a security check
  2. Preparation: allocate memory space for static variables in the method area, and set the initial value of variables, such as static int a = 3 (Note: in the preparation phase, only static variables in the class (in the method area) are set, not instance variables (in heap memory). Instance variables are assigned during object initialization.)
  3. Parsing: the virtual machine replaces the symbolic reference in the constant pool with the process of direct reference (symbolic reference, for example, I now import) java.util.ArrayList This is even a symbol reference. Direct reference is a pointer or object address. Note that the reference object must be in memory.)

2.1.3 initialization

Initialization is actually an assignment operation, which will execute a < clinit > () method of the class constructor. The compiler automatically collects the assignment actions of all variables in the class. At this time, the static int a = 3 example in the preparation phase will be formally assigned to 3

2.1.4 unloading

GC unloads useless objects from memory

Loading sequence of type 2.2 loader

The order of loading a class also has priority. The order of the class loader from the bottom to the top is like this

  1. BootStrap ClassLoader:rt.jar
  2. Extension classloader: load the extended jar package
  3. App classloader: the jar package under the specified classpath
  4. Custom classloader: Custom classloader

2.3 parent appointment mechanism

When a class receives a load request, it will not try to load it by itself, but delegate it to its parent class. For example, I want to create a new person, which is our custom class. If we want to load it, we will delegate app first Classloader, only when the parent class loader feedback that it can’t complete the request (that is, the parent class loader can’t find the required class to load), the child class loader will try to load by itself

The advantage of this is that the load is located in the rt.jar No matter which loader loads the classes in the package, they will be eventually entrusted to bootstrap classloader for loading, which ensures that the same result can be obtained by using different class loaders.

In fact, this is also an isolation function, to avoid our code affecting the JDK code. For example, I want to have one now

public class String(){
    public static void main(){sout;}
}
Copy code

In this case, our code will definitely report an error, because it was found during loading rt.jar In String.class And it turns out that there’s no main method

3、 Runtime data area

3.1 local method stack and program counter

For example, if we click the source code of the thread class now, we will see that its start0 method is modified with a native keyword, and there is no method body. This method modified with native is a local method, which is implemented in C, and then these methods are generally put in an area called the local method stack.

The program counter is actually a pointer, which points to the next instruction to be executed in our program. It is also the only memory area that will not have outofmemoryerror, and the memory space occupied is so small that it can be ignored. This memory only represents the line number indicator of the bytecode executed by the current thread. Bytecode parser selects the next bytecode instruction to be executed by changing the value of this counter.

If the native method is executed, the pointer will not work.

3.2 method area

The main function of the method area is to store the metadata information, constants and static variables of the class. When it stores too much information, it will report an error when it cannot meet the memory allocation.

3.3 virtual machine stack and virtual machine heap

In a word: stack operation, stack storage. The virtual machine stack is responsible for running the code, and the virtual machine heap is responsible for storing the data.

3.3.1 concept of virtual machine stack

It is a memory model for Java method execution. It stores local variables, dynamic linked lists, method exits, and stack operations (in stack and out stack), and the thread is exclusive. At the same time, if we hear the local variable table, we are talking about the virtual machine stack

public class Person{
    int a = 1;
    public void doSomething(){
        int b = 2;
    }
}
Copy code

3.3.2 exception of virtual machine stack

If the depth of the stack requested by the thread is greater than the maximum depth of the virtual machine stack, theStackOverflowError(this error often occurs in recursion). Java virtual machine can also be expanded dynamically, but with the expansion, it will continue to apply for memory. When it is unable to apply for enough memory, it will report an errorOutOfMemoryError

3.3.3 life cycle of virtual machine stack

For the stack, there is no garbage collection. As long as the program runs, the stack space will be released naturally. The life cycle of the stack is the same as that of the thread.

Here is a supplementary sentence: the eight basic types of variables + object reference variables + instance methods all allocate memory in the stack.

3.3.4 execution of virtual machine stack

We often talk about stack frame data, which is called stack frame in the JVM. Putting it in Java is actually a method, and it is also stored in the stack.

The data in the stack is in the format of stack frame, which is a data set about method and runtime data. For example, if we execute a method a, a stack frame A1 will be generated correspondingly, and then A1 will be pushed into the stack. Similarly, method B will have a B1 and method C will have a C1. When the thread is finished, the stack will pop up C1 first, then B1 and A1. It is a first in, last out, last in, first out principle.

3.3.5 reuse of local variables

The local variable table is used to store the method parameters and the local variables defined inside the method. Its capacity takes slot as the smallest unit, and a slot can store data types within 32 bits.

The virtual machine uses the local variable table through index positioning, and the range is [0, number of slots in the local variable table]. The parameters in the method will be arranged in a certain order in the local variable table. As for how to arrange them, we can not care. In order to save stack frame space, these slots can be reused. When the method execution position exceeds a variable, the slot of this variable can be reused by other variables. Of course, if we need reuse, our garbage collection will not move the memory.

3.3.6 concept of virtual machine heap

JVM memory is divided into heap memory and non heap memory, and heap memory is also divided into heap memory and non heap memoryYoung generationandOld age, while non heap memory isPermanent generation. The younger generation will be divided into two groupsEdenandSurvivorDistrict. Survivor will also be divided intoFromPlaceandToPlaceThe survivor area of toplace is empty. The default proportions of Eden, fromplace and toplace are8:1:1. Of course, this thing can also be dynamically adjusted according to the rate of generating objects through a – XX: + usepsadaptive survivorsize policy parameter

Objects are stored in heap memory. Garbage collection is to collect these objects and then send them to GC algorithm for collection. As we have already said, non heap memory is the method area. Permanent generation has been removed in 1.8, and the substitute is a Metaspace. The biggest difference is that Metaspace does not exist in the JVM and uses local memory. And there are two parameters

Metaspacesize: initializes the size of the meta space to control the occurrence of GC
Maxmetaspacesize: limit the upper limit of the size of the meta space to prevent taking up too much physical memory.
Copy code

The reason for the removal can be roughly understood: the change made by integrating hotspot JVM and JRockit VM, because JRockit has no permanent generation, but it also indirectly solves the problem of permanent generation of oom.

3.3.7 introduction of Eden’s young generation

When we create a new object, we will first put a piece of memory divided by Eden as the storage space, but we know that the heap memory is shared by threads, so it is possible that two objects share the same memory. Here, the processing of JVM is that each thread will apply for a piece of continuous memory space in advance and specify the location of the object. If the space is insufficient, it will apply for more than one piece of memory space. This operation will be called TLAB. If you are interested, you can learn about it.

When the Eden space is full, an operation called minor GC will be triggered, and the surviving objects will move to the survivor0 area. When the survivor0 area is full, the minor GC will be triggered, and the surviving object will be moved to the survivor1 area. At this time, the from and to pointers will be exchanged, so as to ensure that one survivor area is empty and the survivor area pointed to by to is empty for a period of time. Objects that survive multiple minor GCS(The survival judgment here is 15 times, and the corresponding virtual machine parameter is – XX: maxtenuringthreshold. Why 15? Because hotspot will record the age in the tag field of the object, and the space allocated is only 4 bits, so it can only record 15 at most)It will move to the old days. In the old age, long-lived objects are stored. When they are full, we often hear that full GC will be triggered. During this period, all threads will stop waiting for GC to complete. Therefore, for applications with high response requirements, we should try to reduce the occurrence of full GC, so as to avoid the problem of response timeout.

In addition, when the old age area is unable to save objects after full GC is executed, oom will be generated. At this time, the heap memory in the virtual machine is insufficient. The reason may be that the size of the heap memory setting is too small. This can be adjusted by the parameters – XMS, – Xmx. It can also be that the objects created in the code are large and numerous, and they have been referenced all the time, so garbage collection cannot collect them for a long time.

Vernacular brings you to know JVM

3.3.8 how to judge whether an object needs to be killed

Vernacular brings you to know JVM

The program counter, virtual machine stack and local method stack in the figure live with the thread. Memory allocation and recycling are deterministic. With the end of the thread, the memory is naturally recycled, so there is no need to consider the problem of garbage collection. However, Java heap and method area are different. Each thread is shared, and memory allocation and recycling are dynamic. Therefore, the garbage collector focuses on heap and method memory.

Before recycling, it is necessary to determine which objects are still alive and which are dead. The following describes the calculation method of the two foundations

1. Reference counter calculation: add a reference counter to the object. Each time the object is referenced, the counter will be increased by one, and when the reference fails, it will be decreased by one. When the counter is equal to 0, it will not be used again. However, this method has a situation that GC can’t recycle when there is a circular reference to an object.

2. Reachability analysis and calculation: This is a kind of implementation similar to binary tree, which takes a series of GC roots as the starting surviving object set, searches down from this node, and the search path becomes the reference chain, and adds the objects that can be referenced by the set to the set. Search when an object does not use any reference chain to GC roots, the object is not available. Mainstream commercial programming languages, such as Java, C #, all rely on this method to determine whether an object is alive or not.

The objects that can be used as GC roots in Java language can be divided into the following types:

  1. Object (local variable) referenced in virtual machine stack (local method table in stack frame)
  2. Objects referenced by static variables in the method area (static variables)
  3. Object referenced by a constant in the method area
  4. Objects referenced by JNI in the local method stack (i.e. native modified methods) (JNI is the way that Java virtual machine calls the corresponding C function, through which new Java objects can be created. And JNI will mark all the objects they point to as non recyclable for local or global references of objects.)
  5. Started and not terminated Java threads

The advantage of this method is that it can solve the problem of circular reference, but its implementation needs a lot of resources and time, and it also needs GC (its analysis process reference relationship cannot change, so it needs to stop all processes)

3.3.9 how to declare the real death of an object

The first thing to mention is a man namedfinalize()How to do it

Finalize() is a method of the object class. The finalize() method of an object will only be automatically called once by the system. The object that escapes death through the finalize() method will not be called again the second time.

Supplementary sentence: do not advocate calling finalize () in procedure to save oneself. It is recommended to forget the existence of this method in Java programs. Because the execution time is uncertain, even if it is executed, it is not sure (the abnormal exit of Java program), and the running cost is too high to guarantee the calling sequence of each object (even in different threads). In Java 9, it has been marked asdeprecated, and java.lang.ref . cleaner (that is, the set of strong, soft, weak, and phantom references) has gradually replaced it, which will be lighter and more reliable than the one from finalize.
  

Vernacular brings you to know JVM

At least two markers are needed to judge the death of an object

  1. If an object does not find a reference chain connected to GC roots after reachability analysis, it will be marked for the first time and filtered. The condition of judgment is to determine whether the object needs to execute the finalize () method. If it is necessary for the object to execute the finalize () method, it is put into the f-queue queue.
  2. GC marks the objects in f-queue twice. If an object is re associated with any object in the reference chain in the finalize() method, it will be removed from the “about to recycle” collection when it is marked twice. If the object has not escaped successfully at this time, it can only be recycled.

If we are sure that the object is dead, how can we recycle the garbage

3.4 garbage collection algorithm

Will not be very detailed expansion, commonly used are mark removal, copy, mark sorting and generation collection algorithm

3.4.1 mark clearing algorithm

Mark clearing algorithm is divided into two stages: mark and clear. Mark all the objects that need to be recycled, and then recycle them uniformly. This routine is very simple, but there are also shortcomings, the subsequent algorithms are based on this basis to improve.

In fact, it marks the dead object as free memory, and then records it in a free list. When we need a new object, the memory management module will look for free memory from the free list to distribute it to the new object.

The disadvantage is that the efficiency of marking and clearing is relatively low. And this approach will make the memory fragmentation is very much. As a result, if we need to use large memory blocks, we can not allocate enough continuous memory. For example, the figure below

Vernacular brings you to know JVM

At this time, the available memory blocks are scattered, which leads to the problem of large memory objects just mentioned

3.4.2 replication algorithm

In order to solve the problem of efficiency, replication algorithm appears. It divides available memory into two equal parts according to its capacity, and uses only one of them at a time. Like survivor, you can also use the two pointers from and to. When the fromplace is full, copy the surviving object to another toplace, and then exchange the contents of the pointer. This solves the problem of debris.

The cost of this algorithm is to shrink the memory, so the efficiency of heap memory will become very low

Vernacular brings you to know JVM

However, they are not allocated according to the ratio of 1:1, which is similar to the fact that Eden and survivor are not equal.

3.4.3 mark sorting algorithm

The replication algorithm has some efficiency problems when the object survival rate is high. The marking process is still the same as the “mark clear” algorithm, but the next step is not to clean up the recyclable objects directly, but to make all the surviving objects move to one end, and then clean up the memory outside the boundary directly

Vernacular brings you to know JVM

3.4.4 generational collection algorithm

This algorithm has no new idea, just divides memory into several blocks according to the different object lifetime. Generally, Java heap is divided into new generation and old generation, so that the most appropriate collection algorithm can be adopted according to the characteristics of each era. In the new generation, it is found that a large number of objects die and only a small number survive in each garbage collection, so the replication algorithm is selected, and the collection can be completed at a small cost of replication. Because of the high survival rate of objects and no extra space to allocate and guarantee them, the old generation must use “mark clean” or “mark clean” algorithm to recycle them.

To put it bluntly, each of the eight immortals has his own magic power when crossing the sea.

3.5 (learn about) all kinds of garbage collectors

Garbage collector in hotspot VM, and applicable scenarios

Vernacular brings you to know JVM

As of jdk8, the default garbage collectors are parallel scavenge and parallel old

Starting with jdk9, the G1 collector becomes the default garbage collector
At present, G1 recycler has the shortest pause time and no obvious shortcomings, so it is very suitable for web applications. When testing web application in jdk8, the heap memory is 6G and the new generation is 4.5g, parallel scavenge recycles the new generation, and the pause is as long as 1.5 seconds. The G1 recycler only pauses 0.2 seconds to recover the same size Cenozoic.

3.6 common parameters of JVM

There are many parameters of JVM. Here are just a few important ones. You can also get these information through various search engines.

Parameter name

meaning

Default value

explain

-Xms

Initial heap size

1 / 64 of physical memory (< 1GB)

By default (minheapfreeratio parameter can be adjusted), when the free heap memory is less than 40%, the JVM will increase the heap to the maximum limit of – Xmx

-Xmx

Maximum heap size

1 / 4 of physical memory (< 1GB)

By default (maxheapfreeratio parameter can be adjusted), when the free heap memory is greater than 70%, the JVM will reduce the heap to the minimum limit of – XMS

-Xmn

Younger generation size (1.4or)

Note: the size here is (Eden + 2 survivor space). It is different from the New Gen shown in jmap – heap. The size of the whole heap = the size of the younger generation + the size of the older generation + the size of the persistent generation (permanent generation). Increasing the size of the younger generation will reduce the size of the older generation. This value has a great impact on the system performance, and sun officially recommends the configuration as 3 / 8 of the whole heap

-XX:NewSize

Set younger generation size (for 1.3 / 1.4)

-XX:MaxNewSize

Maximum value of young generation (for 1.3 / 1.4)

-XX:PermSize

Setting the initial value of perm Gen

1 / 64 of physical memory

-XX:MaxPermSize

Set persistent generation maximum

1 / 4 of physical memory

-Xss

Stack size per thread

After jdk5.0, the stack size of each thread is 1m. Before, the stack size of each thread was 256K. The memory size required by more applicable threads should be adjusted. Under the same physical memory, reducing this value can generate more threads. However, the operating system still has a limit on the number of threads in a process, which cannot be generated indefinitely, The experience value is about 3000 ~ 5000. For small applications, if the stack is not very deep, it should be 128K. For large applications, 256K is recommended. This option has a great impact on performance and needs strict testing. (Headmaster) it’s very similar to the explanation of the threadstack size option, but the official document doesn’t seem to explain it. There is a sentence in the Forum: “XSS is translated in a VM flag named threadstack size”

-XX:NewRatio

The ratio of young generation (including Eden and two survivors) to old generation (excluding persistent generation)

-20: Newratio = 4 means that the ratio of the young generation to the old generation is 1:4, the young generation accounts for 1 / 5 of the whole stack, XMS = Xmx, and XMN is set, so this parameter does not need to be set.

-XX:SurvivorRatio

The ratio of Eden area to survivor area

The ratio of two survivor regions to one Eden region is 2:8, and one survivor region accounts for 1 / 10 of the whole young generation

-XX:+DisableExplicitGC

close System.gc ()

This parameter requires rigorous testing

-XX:PretenureSizeThreshold

How large is the object directly allocated in the old generation

0

The new generation of unit byte is invalid when parallel scavengegc is used. Another case is that large array objects are allocated directly in the old generation, and there is no external reference object in the array

-XX:ParallelGCThreads

Number of threads in parallel collector

This value is best configured to be equal to the number of processors and is also applicable to CMS

-XX:MaxGCPauseMillis

Maximum time (maximum pause time) for each young generation garbage collection

If this time cannot be met, the JVM will automatically adjust the younger generation size to meet this value

In fact, there are also some printing and CMS parameters, which will not be listed here one by one

4、 Some aspects of JVM tuning

According to the knowledge of the JVM just involved, we can try to tune the JVM, mainly the heap memory

The size of shared data area of all threads = new generation size + old generation size + persistent generation size. The size of persistent generation is 64M. So increasing the younger generation in the Java heap will reduce the size of the older generation (because the older generation uses fullgc to clean up, so if the older generation is too small, it will increase fullgc). This value has a great impact on the system performance, and sun officially recommends that it be configured as 3 / 8 of Java heap.

4.1 adjust maximum heap memory and minimum heap memory

-Xmx – XMS: Specifies the maximum value of Java heap (the default value is 1 / 4 of physical memory (< 1GB)) and the minimum value of initial Java heap (the default value is 1 / 64 of physical memory (< 1GB))

By default (the minheapfreeratio parameter can be adjusted), when the free heap memory is less than 40%, the JVM will increase the heap to the maximum limit of – Xmx. By default (the maxheapfreeratio parameter can be adjusted), when the free heap memory is more than 70%, the JVM will decrease the heap to the minimum limit of – XMS. To put it simply, you keep throwing data into the heap memory. When the remaining size is less than 40%, the JVM will dynamically apply for the memory space, but it will be less than – Xmx. If the remaining size is more than 70%, it will dynamically shrink, but it will not be less than – XMS. It’s that simple

In the development process, the configuration values of – XMS and – Xmx are usually the same. The purpose is to avoid the need to separate and calculate the size of the heap after the Java garbage collection mechanism cleans up the heap.

We execute the following code

System.out.println ("Xmx=" +  Runtime.getRuntime (). Maxmemory() / 1024.0 / 1024 + "m"); // the maximum space of the system
System.out.println ("free mem=" +  Runtime.getRuntime (). Freememory () / 1024.0 / 1024 + "m"); // free space of the system
System.out.println ("total mem=" +  Runtime.getRuntime (). Totalmemory() / 1024.0 / 1024 + "m"); // total available space
Copy code

Note: the Java heap size is set here, that is, the new generation size + the old generation size

Vernacular brings you to know JVM

Set a VM options parameter

-Xmx20m -Xms5m -XX:+PrintGCDetails
Copy code

Vernacular brings you to know JVM

Start the main method again

Vernacular brings you to know JVM

Here, GC pops up an allocation failure, which happened in psyounggen, the young generation

At this time, the applied memory is 18m, and the free memory is 4.214195251464844m

Let’s create a byte array and execute the following code

byte[] b = new byte[1 * 1024 * 1024];
System.out.println (1 m space is allocated to the array);
System.out.println ("Xmx=" +  Runtime.getRuntime (). Maxmemory() / 1024.0 / 1024 + "m"); // the maximum space of the system
System.out.println ("free mem=" +  Runtime.getRuntime (). Freememory () / 1024.0 / 1024 + "m"); // free space of the system
System.out.println("total mem=" + Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");
Copy code

Vernacular brings you to know JVM

At this time, free memory shrinks again, but total memory remains unchanged. Java will try its best to keep the value of total MEM at the minimum heap memory size

byte[] b = new byte[10 * 1024 * 1024];
System.out.println ("10m space is allocated to the array");
System.out.println ("Xmx=" +  Runtime.getRuntime (). Maxmemory() / 1024.0 / 1024 + "m"); // the maximum space of the system
System.out.println ("free mem=" +  Runtime.getRuntime (). Freememory () / 1024.0 / 1024 + "m"); // free space of the system
System.out.println ("total mem=" +  Runtime.getRuntime (). Totalmemory() / 1024.0 / 1024 + "m"); // total available space
Copy code

Vernacular brings you to know JVM

At this time, we create a 10m byte data. At this time, the minimum heap memory can’t support it. We will find that the current total memory has become 15m, which is the result of a memory application.

Now let’s run the code again

System.gc();
System.out.println ("Xmx=" +  Runtime.getRuntime (). Maxmemory() / 1024.0 / 1024 + "m"); // the maximum space of the system
System.out.println ("free mem=" +  Runtime.getRuntime (). Freememory () / 1024.0 / 1024 + "m"); // free space of the system
System.out.println ("total mem=" +  Runtime.getRuntime (). Totalmemory() / 1024.0 / 1024 + "m"); // total available space
Copy code

Vernacular brings you to know JVM

At this time, we manually execute a fullgc, and the memory space of total memory changes back to 5.5m, which is the result of releasing the applied memory.

4.2 adjust the ratio of the new generation to the old generation

-20: Newratio: the ratio of the new generation (Eden + 2 * survivor) to the old generation (excluding the permanent area)

For example: – XX: newratio = 4 means Cenozoic: old age = 1:4, that is, Cenozoic accounts for 1 / 5 of the whole reactor. When XMS = Xmx and XMN is set, this parameter does not need to be set.

4.3 adjust the ratio of survivor area to Eden area

-20: Survivorratio – set the ratio of two survivor regions to Eden

For example, 8 means two Survivor:eden=2 : 8, that is, a survivor accounts for 1 / 10 of the young generation

4.4 set the size of the younger generation and the older generation

-20: Newsize — set the size of the younger generation

-20: Maxnewsize — set the maximum value of young generation

You can test different situations by setting different parameters. Anyway, the optimal solution is of course that the proportion of the official Eden and survivor is 8:1:1. Then, when we just introduced these parameters, we have attached some instructions. You can also see if you are interested. In any case, if the maximum heap memory and the minimum heap memory are different, it will lead to multiple GC, which needs attention.

4.5 summary

Adjust the size of the new generation and the surviving generation according to the actual situation. The official recommendation is that the new generation accounts for 3 / 8 of the Java heap, and the surviving generation accounts for 1 / 10 of the new generation

In oom, remember to dump out of the heap to ensure that you can check the field problems. With the following command, you can output a. Dump file. This file can use visualvm or the Java visualvm tool that comes with Java.

-Xmx20m - xms5m - XX: + heapdumponoutofmemoryerror - XX: heapdumppath = the log path you want to output
Copy code

In general, we can also write scripts to let oom report to us when it appears, which can be solved by sending mail or restarting the program.

4.6 setting of permanent area

-XX:PermSize -XX:MaxPermSize
Copy code

Initial space (1 / 64 of physical memory by default) and maximum space (1 / 4 of physical memory by default). That is to say, when the JVM starts, the persistent area takes up the space of permsize at the beginning. If the space is not enough, it can continue to expand, but it cannot exceed maxpermsize, otherwise it will be oom.

Tips: if oom is thrown even if the heap space is not used up, it may be caused by the persistent area. The heap space actually takes up very little, but the oom is thrown just like the persistent overflow.

4.7 tuning of JVM stack parameters

4.7.1 adjust the stack space of each thread

You can use – XSS: to adjust the stack space of each thread

After jdk5.0, the stack size of each thread is 1m. Before, the stack size of each thread was 256K. In the same physical memory, reducing this value can generate more threads. However, the operating system has a limit on the number of threads in a process, which can not be generated indefinitely. The experience value is about 3000 ~ 5000

4.7.2 setting the size of thread stack

-XXThreadStackSize:
    Set the size of thread stack (0? Means use default stack size)
Copy code

These parameters can be simply tested by writing your own program. Due to the space problem, no demo is provided here

4.8 (can skip directly) introduction to other parameters of JVM

There are many kinds of parameters, so we won’t say we have to go all over it, because we don’t say we have to go to the bottom.

4.8.1 setting the size of memory pages

-XXThreadStackSize:
    Set the size of the memory page. Do not set it too large. It will affect the size of perm
Copy code

4.8.2 quick optimization of setting original type

-XX:+UseFastAccessorMethods:
    Quick optimization of setting the original type
Copy code

4.8.3 setting off manual GC

-XX:+DisableExplicitGC:
    Set off System.gc () (this parameter needs strict testing)
Copy code

4.8.4 setting the maximum age of garbage

-XX:MaxTenuringThreshold
    Set the maximum age of garbage. If it is set to 0, the younger generation will enter the older generation without passing through the survivor area
    For the older generation of more applications, can improve efficiency. If you set this value to a larger value,
    Then the young generation objects will replicate in the survivor area for many times, which can increase the survival time of the young generation objects,
    Increase the probability of being recycled in the younger generation. This parameter is only valid for serial GC
Copy code

4.8.5 speed up compilation

-XX:+AggressiveOpts
Copy code

Speed up compilation

4.8.6 improving lock mechanism performance

-XX:+UseBiasedLocking
Copy code

4.8.7 prohibit garbage collection

-Xnoclassgc
Copy code

4.8.8 setting heap space lifetime

-XX:SoftRefLRUPolicyMSPerMB
    Set the lifetime of softreference in the free space of each megaheap. The default value is 1s.
Copy code

4.8.9 the setting objects are directly assigned to the elderly

-XX:PretenureSizeThreshold
    Set the size of the object to be allocated directly to the elderly generation. The default value is 0.
Copy code

4.8.10 setting the proportion of TLAB in Eden area

-XX:TLABWasteTargetPercent
    Set the percentage of TLAB in Eden area. The default value is 1%. 
Copy code

4.8.11 setting priority YGC

-XX:+CollectGen0First
    Whether YGC should be set before fullgc. The default value is false.
Copy code

finally

“2020 latest Java foundation intensive lecture video tutorial and learning route! 》

It’s really been a long time. I’ve referred to various materials, including geek time’s “deep disassembly of virtual machine” and “Java core technology interview intensive lecture”, Baidu, and the summary of some online courses I’m learning. Hope to help you, thank you.