zoukankan      html  css  js  c++  java
  • 记一次Struts2 内核问题分析解决

    问题场景描述


    生产环境某个处理耗时比较长的接口,吞吐能力极差。客服反馈此功能长期处于毫无响应状态。

    • 具体表现
      系统启动后第一次调用耗时极慢,长时间不响应。紧随之后发起的请求也同时没有响应。
      等待第一次调用响应之后,接口方可正常运行。
      遇到这问题,运维同学表示重启根本不好使。

    • 系统框架
      spring 2.5.6
      struts 2.3.32

    分析定位过程


    Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.79-b02 mixed mode):
    
    "http-bio-8080-exec-10" daemon prio=6 tid=0x000000000de20800 nid=0x17c8 waiting for monitor entry [0x0000000014d2b000]
       java.lang.Thread.State: BLOCKED (on object monitor)
    	at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:826)
    	- waiting to lock <0x00000000f38d3388> (a java.lang.reflect.Method)
    	at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1294)
    	at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
    	at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:117)
    	at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:108)
    	at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1370)
    	at ognl.ASTMethod.getValueBody(ASTMethod.java:91)
    	at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    	at ognl.SimpleNode.getValue(SimpleNode.java:258)
    	at ognl.Ognl.getValue(Ognl.java:470)
    	at ognl.Ognl.getValue(Ognl.java:434)
    	at com.opensymphony.xwork2.ognl.OgnlUtil$3.execute(OgnlUtil.java:352)
    	at com.opensymphony.xwork2.ognl.OgnlUtil.compileAndExecuteMethod(OgnlUtil.java:404)
    	at com.opensymphony.xwork2.ognl.OgnlUtil.callMethod(OgnlUtil.java:350)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:430)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:290)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:251)
    	at org.apache.struts2.interceptor.DeprecationInterceptor.intercept(DeprecationInterceptor.java:41)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:168)
    	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
    	at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:76)
    	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
    	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
    	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:125)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:253)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
    	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:140)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
    	at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:575)
    	at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)
    	at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)
    	at dfh.filter.MainStrutsFilter.doFilter(MainStrutsFilter.java:77)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
    	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
    	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    	- locked <0x00000000f38d88e0> (a org.apache.tomcat.util.net.SocketWrapper)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    	at java.lang.Thread.run(Thread.java:745)
    
    "http-bio-8080-exec-9" daemon prio=6 tid=0x000000000de1f800 nid=0x2f44 waiting on condition [0x0000000014c2f000]
       java.lang.Thread.State: WAITING (parking)
    	at sun.misc.Unsafe.park(Native Method)
    	- parking to wait for  <0x00000000a54cb788> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
    	at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
    	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:104)
    	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:32)
    	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    	at java.lang.Thread.run(Thread.java:745)
    
    "http-bio-8080-exec-8" daemon prio=6 tid=0x000000000f162000 nid=0x2428 waiting on condition [0x0000000014b2e000]
       java.lang.Thread.State: WAITING (parking)
    	at sun.misc.Unsafe.park(Native Method)
    	- parking to wait for  <0x00000000a54cb788> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
    	at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
    	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:104)
    	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:32)
    	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    	at java.lang.Thread.run(Thread.java:745)
    
    "http-bio-8080-exec-7" daemon prio=6 tid=0x000000000f161000 nid=0x3064 waiting on condition [0x0000000014a2e000]
       java.lang.Thread.State: WAITING (parking)
    	at sun.misc.Unsafe.park(Native Method)
    	- parking to wait for  <0x00000000a54cb788> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
    	at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
    	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:104)
    	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:32)
    	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    	at java.lang.Thread.run(Thread.java:745)
    
    "http-bio-8080-exec-6" daemon prio=6 tid=0x000000000f162800 nid=0x2264 waiting for monitor entry [0x000000001492c000]
       java.lang.Thread.State: BLOCKED (on object monitor)
    	at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:826)
    	- waiting to lock <0x00000000f38d3388> (a java.lang.reflect.Method)
    	at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1294)
    	at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
    	at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:117)
    	at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:108)
    	at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1370)
    	at ognl.ASTMethod.getValueBody(ASTMethod.java:91)
    	at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
    	at ognl.SimpleNode.getValue(SimpleNode.java:258)
    	at ognl.Ognl.getValue(Ognl.java:470)
    	at ognl.Ognl.getValue(Ognl.java:434)
    	at com.opensymphony.xwork2.ognl.OgnlUtil$3.execute(OgnlUtil.java:352)
    	at com.opensymphony.xwork2.ognl.OgnlUtil.compileAndExecuteMethod(OgnlUtil.java:404)
    	at com.opensymphony.xwork2.ognl.OgnlUtil.callMethod(OgnlUtil.java:350)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:430)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:290)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:251)
    	at org.apache.struts2.interceptor.DeprecationInterceptor.intercept(DeprecationInterceptor.java:41)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:168)
    	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
    	at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:76)
    	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
    	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229)
    	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:125)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:253)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
    	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:140)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189)
    	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:245)
    	at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
    	at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:575)
    	at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)
    	at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)
    	at dfh.filter.MainStrutsFilter.doFilter(MainStrutsFilter.java:77)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
    	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
    	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    	- locked <0x00000000e0cac298> (a org.apache.tomcat.util.net.SocketWrapper)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    	at java.lang.Thread.run(Thread.java:745)
    

    可以看到有着大量的线程BLOCKED 状态,紧接着查看线程栈内容可以看到阻塞是在调用方法fliter
    但这里并不是问题症结,回头查看栈顶信息可以看到ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:826)

    问题解决方案


    此问题为struts2内核BUG导致,升级struts2版本至2.3.34, 2.5.13可以解决。

    源码细节分析



    • 在多线程场景中,由于OgnlRuntime类中的invokeMethod方法中的不必要的同步处理逻辑,除第一个以外的所有线程都进入BLOCKED状态。
     public static Object invokeMethod(Object target, Method method, Object[] argsArray)
        throws InvocationTargetException, IllegalAccessException
      {
        boolean syncInvoke = false;
        boolean checkPermission = false;
        boolean wasAccessible = true;
    
    
        synchronized (method) {
          if ((_methodAccessCache.get(method) == null))
          {
            if ((!Modifier.isPublic(method.getModifiers())) || (!Modifier.isPublic(method.getDeclaringClass().getModifiers())))
            {
              if (!(wasAccessible = method.isAccessible()))
              {
                 method.setAccessible(true);
                _methodAccessCache.put(method, Boolean.TRUE);
              }
              else {
                _methodAccessCache.put(method, Boolean.FALSE);
              }
            }
            else {
              _methodAccessCache.put(method, Boolean.FALSE);
            }
          }
          if (_methodAccessCache.get(method) == Boolean.TRUE))
          {
            syncInvoke = true;
          }
    
          if (((_securityManager != null) && (_methodPermCache.get(method) == null)) || (_methodPermCache.get(method) == Boolean.FALSE))
          {
            checkPermission = true;
          }
    
        }
    
        Object result;
        if (syncInvoke)
        {
          synchronized (method)
          {
            if (checkPermission)
            {
              try
              {
                _securityManager.checkPermission(getPermission(method));
                _methodPermCache.put(method, Boolean.TRUE);
              } catch (SecurityException ex) {
                _methodPermCache.put(method, Boolean.FALSE);
                throw new IllegalAccessException("Method [" + method + "] cannot be accessed.");
              }
            }
    
            Object result = method.invoke(target, argsArray);
    
            if (!wasAccessible)
            {
              method.setAccessible(false);
            }
          }
        }
        else {
          if (checkPermission)
          {
            try
            {
              _securityManager.checkPermission(getPermission(method));
              _methodPermCache.put(method, Boolean.TRUE);
            } catch (SecurityException ex) {
              _methodPermCache.put(method, Boolean.FALSE);
              throw new IllegalAccessException("Method [" + method + "] cannot be accessed.");
            }
          }
    
          result = method.invoke(target, argsArray);
        }
    
        return result;
      }
    

    因为Object result = method.invoke(target, argsArray);在同步调用代码块中,所有其他线程将被阻塞直到第一个线程退出调用过程。

        public static Object invokeMethod( Object target, Method method, Object[] argsArray )
            throws InvocationTargetException, IllegalAccessException, CacheException
        {
            Object result;
            if ( securityManager != null && !cache.getMethodPerm( method ) )
            {
                throw new IllegalAccessException( "Method [" + method + "] cannot be accessed." );
            }
            MethodAccessEntryValue entry = cache.getMethodAccess( method );
            if ( !entry.isAccessible() )
            {
                // only synchronize method invocation if it actually requires it
                synchronized ( method )
                {
                    if ( entry.isNotPublic() && !entry.isAccessible() )
                    {
                        method.setAccessible( true );
                    }
                    result = method.invoke( target, argsArray );
                    if ( !entry.isAccessible() )
                    {
                        method.setAccessible( false );
                    }
                }
            }
            else
            {
                result = method.invoke( target, argsArray );
            }
            return result;
        }
    

    在接下的版本中,invokeMethod方法将method.invoke( target, argsArray )移出同步调用块;
    同时做if ( !entry.isAccessible() )判断,只有当确实需要同步调用,以保障对象唯一单例的情况下,才调用同步逻辑。

  • 相关阅读:
    stm32 fatfs 文件系统分析和代码解析
    STM32 USB协议和代码分析
    微型跟踪器A产品体验和分析
    辅听一号产品体验和测评
    华为sound x智能音箱初体验
    TPC-H 分析
    论文解析 -- TPC-H Analyzed: Hidden Messages and Lessons Learned from an Influential Benchmark
    Calcite分析 -- Cost
    Calcite分析 -- ConverterRule
    Calcite分析 -- TopDownRuleDriver
  • 原文地址:https://www.cnblogs.com/snifferhu/p/9183740.html
Copyright © 2011-2022 走看看