One literature meeting JVM performance optimization

One literature meeting JVM performance optimization

Actual combat performance optimization

Recognize JVM

Before we drew a picture of the process from the Class file to the class loader, and then to the runtime data area. Now let's enrich and perfect this picture to show the general physical structure of the JVM.

Execution engine: used to execute JVM bytecode instructions

There are two main ways to achieve it:

(1) Translate the input bytecode instruction into another type of virtual machine instruction during loading or execution;

(2) Translate the input bytecode instruction into the instruction set of the host host's local CPU during loading or execution. These two methods correspond to interpretation and execution of bytecode and just-in-time compilation.

9.2 Heap memory overflow

9.2.1 Code

Remember to set the parameters such as -Xmx20M -Xms20M

9.2.2 Running results


Exception in thread "http-nio-8080-exec-2" java.lang.OutOfMemoryError: GC overhead limit exceeded

9.2.3 Review jps and jinfo

9.2.4 Review the manual export of jmap and the automatic export of parameters

Manual export of jmap: jmap -dump:format=b,file=heap.hprof PID

Parameters are automatically exported:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heapdump.hprof

9.3 Method area memory overflow

For example, add Class information to the method area

9.3.1 asm dependency and Class code

9.3.2 Code

Set the size of Metaspace, such as -XX:MetaspaceSize=50M -XX:MaxMetaspaceSize=50M

9.3.3 Running results


9.4 Virtual Machine Stack

9.4.1 Code Demo StackOverFlow

9.4.2 Running results

9.4.3 Description

Stack Space is used to push the Stack Frame into the recursive call of the method. So when the recursive call is too deep, it may run out of Stack Space and explode StackOverflow errors.

-Xss128k: Set the stack size of each thread. After JDK 5, the stack size of each thread is 1M, and the stack size of each thread is 256K before. Adjust according to the size of the memory required by the threads of the application. 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 around 3000~5000.

The size of the thread stack is a double-edged sword. If it is set too small, stack overflow may occur, especially when there is a recursive or large loop in the thread, the possibility of overflow is greater. If the value is set too large, there will be Affect the number of created stacks, if it is a multi-threaded application, there will be a memory overflow error.

9.5 Thread deadlock

9.5.1 Code

9.4.2 Running results

9.4.3 jstack analysis

Pull the print information to the end to find

9.4.4 jvisualvm

Dump thread information

9.6 Garbage collection

After the memory is used, it is inevitable that the memory space will need to be garbage collected when it is not enough or reaches the set value.

9.6.1 Timing of garbage collection

GC is automatically completed by the JVM, depending on the JVM system environment, so the timing is uncertain.

Of course, we can perform garbage collection manually, such as calling the System.gc() method to notify the JVM to perform a garbage collection, but the specific timing of the operation cannot be controlled. That is to say, System.gc() just informs you to recycle, and the JVM decides when to recycle.

However, it is not recommended to manually call this method because it consumes a lot of resources.

Generally, garbage collection will occur in the following situations

(1) When Eden area or S area is not enough

(2) There is not enough space in the old age

(3) The method area is not enough space

(4) System.gc()

Although the timing of garbage collection is uncertain, it can be combined with a lifetime case of an object before, and the text illustration will sort out the process of heap memory collection again.

A lifetime of an object

I am an ordinary Java object. I was born in the Eden area. In the Eden area, I also saw a little brother who looked like me. We played in the Eden area for a long time.

One day there were too many people in the Eden area, and I was forced to go to the "From" area of ​​the Survivor area. Since I went to the Survivor area, I started to drift. Sometimes in the "From" area of ​​Survivor, there are At the time I was in the "To" area of ​​Survivor, and I had no fixed home. Until I was 18 years old, my father said that I was an adult and that I should go to the society to break into the world.

So I went to the old generation. In the old generation, there are a lot of people, and they are all quite old. I also know a lot of people here. In the old generation, I lived for 20 years (each GC plus one year), and then I was recycled.

9.6.2 Preparation of the experimental environment

My local machine uses jdk1.8 and tomcat8.5, you can also use tomcat on linux, and then download the gc log.

9.6.3 GC log file

Review the sublimation garbage collector diagram

If you want to analyze the log information, you have to get the GC log file first, so you have to configure it first, and you have seen these parameters before.

-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:$CATALINA_HOME/logs/gc.log

For example, open catalina.bat in windows and add

set JAVA_OPTS=%JAVA_OPTS% -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:gc.log

In this way, when using startup.bat to start tomcat, you can get the gc.log file in the current directory

You can see that ParallelGC is used by default Parallel GC log

[Throughput priority]

2019-06-10T23:21:53.305+0800: 1.303: [GC (Allocation Failure) [PSYoungGen: 65536K[Young area before recovery]->10748K[Young area after recovery](76288K[Young area total size])] 65536K [The entire heap is collected before]->15039K[After the entire heap is collected](251392K[total size of the entire heap]), 0.0113277 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]

`Note` If there is a discrepancy between the recovered difference, it means that this part of the space is released by the Old area CMS log

【Pause time priority】

parameter settings


Restart tomcat to get the gc log. The log format here is similar to the above, without analysis. G1 log

G1 log format reference link:

【Pause time priority】


parameter settings


9.6.4 GC log file analysis tool gceasy

You can compare the throughput and pause time of different garbage collectors GCViewer

9.6.5 G1 tuning

The basis for judging whether to use the G1 garbage collector

(1) More than 50% of the heap is occupied by surviving objects

(2) The speed of object allocation and promotion has changed greatly

(3) The garbage collection time is relatively long

(1) Use G1GC garbage collector: -XX:+UseG1GC

Modify configuration parameters, get gc log, use GCViewer to analyze throughput and response time

Throughput MinPause MaxPause AvgPause GCcount

99.16% 0.00016s 0.0137s 0.00559s 12

(2) Adjust the memory size and then obtain gc log analysis


For example, set the size of heap memory, get gc log, use GCViewer to analyze throughput and response time

Throughput MinPause MaxPause AvgPause GCcount

98.89% 0.00021s 0.01531s 0.00538s 12

(3) Adjust the maximum pause time

-XX:MaxGCPauseMillis=200 sets the maximum GC pause time indicator

For example, set the maximum pause time, get the gc log, use GCViewer to analyze the throughput and response time

Throughput MinPause MaxPause AvgPause GCcount

98.96% 0.00015s 0.01737s 0.00574s 12

(4) Heap memory usage percentage when starting concurrent GC

-XX:InitiatingHeapOccupancyPercent=45 G1 uses it to trigger concurrent GC cycles, based on the usage rate of the entire heap, not just the usage ratio of a certain generation of memory. A value of 0 means "always execute the GC cycle)'. The default value is 45 (for example, 45% of all or 45% used).

For example, set the percentage parameter, get the gc log, use GCViewer to analyze the throughput and response time

Throughput MinPause MaxPause AvgPause GCcount

98.11% 0.00406s 0.00532s 0.00469s 12

9.6.6 Best Practices for G1 Tuning

Official website recommendations:


(1) Do not manually set the size of the young and old generations, just set the size of the entire heap

The G1 collector will adjust the size of the young and old generations by itself during operation

In fact, the speed and age of object promotion are adjusted by the size of the adapt generation, so as to achieve the pause time goal set for the collector

If the size is manually set, it means that the automatic tuning of G1 is abandoned

(2) Continuously adjust the suspension time target

Under normal circumstances, this value can be set to 100ms or 200ms (it will be different under different circumstances), but it is not reasonable if it is set to 50ms. If the pause time is set too short, it will cause G1 to fail to keep up with the rate of garbage generation. Eventually degenerate into Full GC. Therefore, the tuning of this parameter is a continuous process, gradually adjusting to the best state. Pause time is only a goal and cannot always be met.

(3) Use -XX:ConcGCThreads=n to increase the number of marked threads

If the IHOP threshold is set too high, there may be a risk of transfer failure, such as insufficient space when the object is transferred. If the threshold is set too low, the marking period will run too frequently, and it is possible that the space cannot be reclaimed during the mixed collection period.

> If the IHOP value is set reasonably, but when the concurrent cycle time is too long, you can try to increase the number of concurrent threads and increase ConcGCThreads.

(4) MixedGC tuning





(5) Appropriately increase the heap memory size

9.7 A picture summarizing JVM performance optimization

The full text is over! thanks for watching