An application that consumes a lot of CPU is usually due to an endless loop, in addition to being truly computationally intensive.

Taking a recent actual fault as an example, this paper introduces how to locate and solve this problem.

  

According to the top command, the Java process whose PID is 28555 occupies 200% of the CPU.

Using the following command, you can further determine that the Tomcat process is faulty. But how do you locate a specific thread or code?

    $ ps -aux | grep PID
Copy the code

First display the thread list:

    $ ps -mp PID -o THREAD,tid,time
Copy the code

  

Found thread 28802 with highest CPU usage for almost 2 hours!

Second, convert the required thread ID to hexadecimal format:

    $ printf "%x\n" TID
Copy the code

  

Finally, the thread stack is printed:

    $ jstack PID | grep TID -A 60
Copy the code

I found the offending code!

Now look at the code: shortSocketio.readbytes (shortsocketio.java :106)

ShortSocketIO is an application-encapsulated utility class that communicates with short sockets. The readBytes function is coded as follows:

public byte[] readBytes(int length) throws IOException {

    if ((this.socket == null) | | (!this.socket.isConnected())) {

        throw new IOException("++++ attempting to read from closed socket");

    }

    byte[] result = null;

    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    if (this.recIndex >= length) {

           bos.write(this.recBuf, 0, length);

           byte[] newBuf = new byte[this.recBufSize];

           if (this.recIndex > length) {

               System.arraycopy(this.recBuf, length, newBuf, 0.this.recIndex - length);

           }

           this.recBuf = newBuf;

           this.recIndex -= length;

    } else {

           int totalread = length;

           if (this.recIndex > 0) {

                totalread -= this.recIndex;

                bos.write(this.recBuf, 0.this.recIndex);

                this.recBuf = new byte[this.recBufSize];

                this.recIndex = 0;

    }

    int readCount = 0;

    while (totalread > 0) {

         if ((readCount = this.in.read(this.recBuf)) > 0) {

                if (totalread > readCount) {

                      bos.write(this.recBuf, 0, readCount);

                      this.recBuf = new byte[this.recBufSize];

                      this.recIndex = 0;

               } else {

                     bos.write(this.recBuf, 0, totalread);

                     byte[] newBuf = new byte[this.recBufSize];

                     System.arraycopy(this.recBuf, totalread, newBuf, 0, readCount - totalread);

                     this.recBuf = newBuf;

                     this.recIndex = (readCount - totalread); } totalread -= readCount; }}}Copy the code

The problem is the part of the code that is marked red. If this.in.read() returns less than or equal to zero, the loop continues. This can happen when the network is congested.

How this is modified depends on how the business logic should treat this particular case.

Finally, summarize the methods and skills to troubleshoot CPU faults:

1, top command: Linux command. You can view real-time CPU usage. You can also view the CPU usage in a recent period.

2. PS command: Linux command Powerful process status monitoring commands. You can view the current CPU usage of the process and the threads in the process. Sample data belonging to the current state.

Jstack: a command provided by Java. You can view the current thread stack status of a process. The output of this command can be used to locate the current running status of all threads of a process, the running code, whether they are deadlocked, and so on.

Pstack: Linux command. You can view the current thread stack status of a process.