At the beginning:

Today 2B elder brother wants to share a hard goods with everybody, why ah? Because there are two good things:

First, the elder brother upgraded LV2 ha ha mood times cool.

Two, get the company to give 2,000 shares

Stayed in the company for 2 years, finally became a good brother of Brother Tonge.

CMS collector combat:

Here we go. Ready or not

Build the Spring Boot project:

Simulated business scenario code:

@restController Public class IndexController {/*** * Saves the big object * @return
 */
@GetMapping("/put")
public String process() {
   ArrayList<User> users = queryUsers();
   for(User User :users){//TODO service operation}return "ok";
}
private ArrayList<User> queryUsers() {
   ArrayList<User> users = new ArrayList<>();
   for (int i = 0; i < 50000; i++) {
      users.add(new User(i, "java2b"));
   }
   returnusers; }}Copy the code
public class User { private int id; private String name; private byte[] data; public User(int id, String name) { this.id = id; this.name = name; data=new byte[1 * 128 * 1024]; }}Copy the code

Output collector information:

/*** * Prints JVM information * @return
 */
@GetMapping("/info")
public String info() {
   List<GarbageCollectorMXBean> garbages = ManagementFactory.getGarbageCollectorMXBeans();
   StringBuilder stringBuilder = new StringBuilder();
   for (GarbageCollectorMXBean garbage : garbages) {
      stringBuilder.append(Garbage collector: name = + garbage.getName() + ", collect =" + garbage.getCollectionCount() + ", total time spent ="
              + garbage.getCollectionTime());
      // + ", memory area name =" + Arrays.deepToString(garbage.getMemoryPoolNames()));
      stringBuilder.append("\r\n");
   }
   MemoryMXBean memory = ManagementFactory.getMemoryMXBean();
   MemoryUsage headMemory = memory.getHeapMemoryUsage();
   long MB = 1024 * 1024;
   stringBuilder.append("The head pile.");
   stringBuilder.append(Initial (M) : "\ t" + headMemory.getInit() / MB);
   stringBuilder.append("\t maximum (upper limit)(M):" + headMemory.getMax() / MB);
   stringBuilder.append("\t Current (used)(M):" + headMemory.getUsed() / MB);
   stringBuilder.append("\t Committed memory (requested)(M):" + headMemory.getCommitted() / MB);
   stringBuilder.append("\t Usage rate :" + headMemory.getUsed() * 100 / headMemory.getCommitted() + "%");
   return stringBuilder.toString();
}
Copy the code

Generate jar packages for deployment to the server

Startup parameters:

java -Xms256m -Xmx256m -verbose:gc -Xloggc:/root/jvm/gc-cms.log -XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintHeapAtGC -XX:HeapDumpPath=/root/jvm/dump.hprof -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCTimeStamps -XX:+PrintCommandLineFlags -XX:+PrintFlagsFinal -XX:+PrintGCDetails -XX:+UseCMSCompactAtFullCollection -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false- Dcom. Sun. Management. Jmxremote. Port = 6666 - Djava. Rmi. Server hostname = 192.168.0.31 - jar / root/JVM/JVM - web - 0.0.1 - the SNAPSHOT. Jar > catalina. Out &Copy the code

Here’s what the JVM parameters mean.

JVM parameters:

The JVM parameter meaning
-XX:-CMSPrecleaningEnabled Without pre-cleaning, those who have spent our previous articles know that the CMS will have a pre-cleaning job between concurrent marking and re-marking, and that the pass will try to wait for a YGC within 5 seconds. So as not to spend too much time tagging the objects of the new generation in the later relabeling phase.
-XX:+UseConcMarkSweepGC This parameter starts the CMS collector. The default new generation is ParNew, or you can set Serial to the new generation collector. This parameter is equivalent to -xconcGC.
-XX:ParallelGCThreads Since it is a parallel processor, you can of course specify the number of threads. The default number of concurrent threads is (ParallelGCThreads + 3) / 4).
-XX:ConcGCThreads Or – XX: ParallelCMSThreads; In addition to the thread setting method above, you can manually set the number of concurrent CMS threads using either of these two parameters
-XX:CMSInitiatingOccupancyFraction Because the CMS collector is not exclusive and the application is still working at garbage collection time, you need to set aside enough memory for the application otherwise the FGC will be triggered. When do you run the CMS GC? This parameter indicates the percentage of memory usage in the old years. When this threshold is reached, the CMS is executed. The default is 68. If the memory growth is rapid in the old age, lower the threshold to avoid FGC. If the memory growth is slow, increase the threshold to reduce THE CMS GC times. Improved throughput.
– XX: + UseCMSCompactAtFullCollection Since CMS uses a tag cleaning algorithm, memory fragmentation is unavoidable. This parameter specifies a defragmentation after each CMS.
-XX:CMSFullGCsBeforeCompaction Since each defragmentation will affect performance, you can use this parameter to set how many CMS you need to perform a defragmentation, that is, memory compression.
-XX:+CMSClassUnloadingEnabled Allows collection of class metadata.
-XX:CMSInitiatingPermOccupancyFraction When this percentage of permanent area usage is reached, CMS reclamation is started (provided -xx :+CMSClassUnloadingEnabled is enabled).
-XX:UseCMSInitiatingOccupancyOnly The CMS is reclaimed only when the threshold is reached.
XX:CMSWaitDuration=2000 Due to the simplicity of the CMS GC condition, the JVM has a thread that periodically scans the Old section at intervals specified by this parameter (in milliseconds), which defaults to 2s.

JVM tool parameters:

The JVM parameter meaning
-XX:+PrintGCDateStamps Prints the GC log timestamp
-XX:+PrintGCDetails Print GC details
-XX:+PrintGCTimeStamps This is how long garbage collection has taken since the JVM started running
-Xloggc: Prints garbage collection information to the specified file
-verbose:gc Printing GC Logs
-XX:+PrintGCApplicationStopedTime Check the application pause times caused by GC
XX:+PrintTenuringDistribution Object promotion log
-XX:+HeapDumpOnOutOfMemoryError Dump file is output when memory overflow occurs

Startup effect:

Access:

It is not hard to find that the new generation uses parNew’s CMS for the elderly

Request put:

Let’s see what happens when we access the put method via HTTP:

The effect is as follows:

During the run, we found that a large number of objects were aged, triggering the Full GC, and the CMS was collecting.

Usage reached 99% and CMS never stopped:

Log analysis:

Log Analysis Version 1.0:

Let’s extract a log and analyze it

0K->63K(64K), 0.0047147 secs] 10258K->6780K(46144K), [Metaspace: [Times: user= 0.03sys =0.00, real=0.00 secs][Times: user= 0.03sys =0.00, real=0.00 secs]

The log consists of four parts:

Full GC:

This is a Minor garbage collection, but it doesn’t mean that only the Cenozoic generation will be collected, and all existing generations will be STW.

Allocation Failure:

This indicates that GC is caused because there is not enough space in the young generation to store new data.

10258K->6780K(46144K) : the unit is KB

The three parameters are: the capacity used by the memory region (here is the young generation) before GC, the capacity used by the memory region after GC, and the total capacity of the memory region.

0.0047613 secs:

The GC time of this memory area, in seconds

[Times: user=0.04 sys=0.00, real= 0.05secs] :

Indicates the user-mode time, kernel-mode time, and total time respectively

Log Analysis Version 2.0:

Online GCEasy was used for analysis. We opened the website and uploaded the GC log of our production, as shown in the figure:

Optimization problem:

Four problems that can be optimized are listed

Throughput statistics: 97.39%

Memory changes for each generation:

The elapsed time of the CMS garbage collector at different times

Classification and time consuming of GC occurrences

Locating problems:

We use the production snapshot file to locate the problem:

JProfiler:

Download it locally and open it for viewing through JProfiler

View large objects:

We can see that the ArrayList collection takes up 96% of the memory, so let’s see which piece of code uses our ArrayList collection a lot.

Find the corresponding code

From this code we can see that the put method makes heavy use of the ArrayList collection causing memory overflow OOM

Conclusion:

I believe we all understand the actual combat, the general process is:

1, enough to simulate the SpringBoot project of real mass user scenarios

2. Configure JVM parameters and deploy run monitoring data to generate log files

3. Identify the problem by analyzing the log file.

Need the above code and software friends, you can pay attention to my wechat: Java2B, we can practice to deepen the impression.

That’s all for today. Feel good welcome to focus on praise, your point praise attention is the biggest power of my good article.

Can see this are awesome people, trouble to help click a like attention, next I continue to bring CMS and G1 combat PK comparison, graphical comparison to see more intuitive.

Pay attention and don't get lost.Copy the code