Description
Whenever significant number of threads exhibit same/repetitive stack trace then those stack trace has to be investigated. It may be indicative of performance problems.
Whenever there are any performance problems or bottlenecks in the application most of the threads will start to accumulate on the problematic area. Here are few such scenarios:
- Say your SOR or external service is slowing down then significant number of threads will start to wait for it’s response. In such circumstance those threads will exhibit similar stack trace.
- Say a thread acquired a lock & it never released then, then several other threads who are in the same execution path, will get in to the blocked state, exhibiting same stack trace.
- If a loop (for loop, while loop, do..while loop) condition doesn’t terminate then several threads which executes that loop which exhibit same stack trace.
When any of the above scenario occurs application’s performance and availability will be questioned.
Example
Below is an excerpt from a thread dump of a major B2B application, where 225 threads out of 400 threads were exhibiting same stack trace:
"ajp-bio-192.168.100.128-9022-exec-79" daemon prio=10 tid=0x00007f4d2001c000 nid=0x1d1c waiting for monitor entry [0x00007f4ce91fa000] java.lang.Thread.State: BLOCKED (on object monitor) at com.xxxxxxxxx.xx.xxx.xxxx.ReferenceNumberGeneratorDaoImpl.getNextItineryReferenceNumber(ReferenceNumberGeneratorDaoImpl.java:55) - waiting to lock 0x00000006afaa5a60 (a com.xxxxxxxxx.sp.dao.impl.ReferenceNumberGeneratorDaoImpl) at sun.reflect.GeneratedMethodAccessor3112.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149) at org.springframework.orm.hibernate3.HibernateInterceptor.invoke(HibernateInterceptor.java:111) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at com.sun.proxy.$Proxy36.getNextItineryReferenceNumber(Unknown Source) at com.xxxxxxxxx.xx.xxxxxxxx.xxx.ReferenceNumberGeneratorServiceImpl.getNextItineryReferenceNumber(ReferenceNumberGeneratorServiceImpl.java:15) : :
From the stack trace you can infer that thread was blocked and waiting for the lock on the object0x00000006afaa5a60. 225 such threads waiting to obtain lock on this same object. It’s definitely a bad sign. It’s a clear indication of thread starvation.
Now we need to figure out who is holding on to the lock. I will grep for the string: “locked “. It shows “ajp-bio-192.168.100.128-9022-exec-84″ acquired the lock and got stuck waiting for response from database. Thus 225 other threads were stuck waiting on it.
“ajp-bio-192.168.100.128-9022-exec-84″ daemon prio=10 tid=0x00007f4d2000a800 nid=0x1d26 runnable [0x00007f4ce6ce1000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:150) at java.net.SocketInputStream.read(SocketInputStream.java:121) at java.io.DataInputStream.readFully(DataInputStream.java:195) at java.io.DataInputStream.readFully(DataInputStream.java:169) at net.sourceforge.jtds.jdbc.SharedSocket.readPacket(SharedSocket.java:850) at net.sourceforge.jtds.jdbc.SharedSocket.getNetPacket(SharedSocket.java:731) - locked (a java.util.concurrent.ConcurrentHashMap) at net.sourceforge.jtds.jdbc.RexxonseStream.getPacket(RexxonseStream.java:477) at net.sourceforge.jtds.jdbc.RexxonseStream.read(RexxonseStream.java:114) at net.sourceforge.jtds.jdbc.RexxonseStream.peek(RexxonseStream.java:99) at net.sourceforge.jtds.jdbc.TdsCore.wait(TdsCore.java:4127) at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1086) - locked (a net.sourceforge.jtds.jdbc.TdsCore) at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQLQuery(JtdsStatement.java:493) at net.sourceforge.jtds.jdbc.JtdxxreparedStatement.executeQuery(JtdxxreparedStatement.java:1032) at com.jolbox.bonecp.PreparedStatementHandle.executeQuery(PreparedStatementHandle.java:174) at com.xxxxxxxx.xx.xxx.xxx.ReferenceNumberGeneratorxxxxxx.getNextItineryReferenceNumber(ReferenceNumberGeneratorxxxxxx.java:65) - locked 0x00000006afaa5a60(a com.xxxxxxxx.xx.xxx.xxx.ReferenceNumberGeneratorxxxxxx) at sun.reflect.GeneratedMethodAccessor3112.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorxxx.invoke(DelegatingMethodAccessorxxx.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149) at org.springframework.orm.hibernate3.HibernateInterceptor.invoke(HibernateInterceptor.java:111) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at com.sun.proxy.$Proxy36.getNextItineryReferenceNumber(Unknown Source) at com.xxxxxxxx.xx.service.xxx.ReferenceNumberGeneratorServicexxx.getNextItineryReferenceNumber(ReferenceNumberGeneratorServicexxx.java:15) at sun.reflect.GeneratedMethodAccessor3031.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorxxx.invoke(DelegatingMethodAccessorxxx.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307) : :
So bottom line is always look for repeating stack traces
Why named as RSI?
Technical definition of Repetitive Strain Injury (RSI) goes as – ‘an injury to the musculoskeletal and nervous systems that may be caused by repetitive tasks, forceful exertions, vibrations, mechanical compression, or sustained or awkward positions’. Similarly when there are performance problems or bottlenecks multiple threads will exhibit same/repetitive stack trace.
Leave a Reply