concurrent.ExecutionException: java.lang.ArrayIndexOutOfBoundsException: 3

Keywords: Programming Java Apache Spring Tomcat

Today's project, because of the use of spring asynchronous concurrent execution, this error occurred. And occasionally, especially when the project is just started, such problems may occur

java.util.concurrent.ExecutionException: java.lang.ArrayIndexOutOfBoundsException: 3
        at java.util.concurrent.FutureTask.report(FutureTask.java:122)
        at java.util.concurrent.FutureTask.get(FutureTask.java:192)
        at com.newpearl.da.service.aggr.performance.report.EmployeePerformanceReportDo.listReport(EmployeePerformanceReportDo.java:75)
        at com.newpearl.da.service.aggr.performance.report.EmployeePerformanceReportDo$$FastClassBySpringCGLIB$$5f785673.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685)
        at com.newpearl.da.service.aggr.performance.report.EmployeePerformanceReportDo$$EnhancerBySpringCGLIB$$97e6d2e4.listReport(<generated>)
        at com.newpearl.da.service.mvc.controller.DaEmployeeReportController.performance(DaEmployeeReportController.java:128)
        at com.newpearl.da.service.mvc.controller.DaEmployeeReportController$$FastClassBySpringCGLIB$$a82a6a.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685)
        at com.newpearl.da.service.mvc.controller.DaEmployeeReportController$$EnhancerBySpringCGLIB$$4d830129.performance(<generated>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)

A Null exception occurred in one test

java.util.concurrent.ExecutionException: java.lang.ArrayIndexOutOfBoundsException
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at com.newpearl.da.service.aggr.performance.report.EmployeePerformanceReportDo.listReport(EmployeePerformanceReportDo.java:75)
	at com.newpearl.da.service.aggr.performance.report.EmployeePerformanceReportDo$$FastClassBySpringCGLIB$$5f785673.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685)
	at com.newpearl.da.service.aggr.performance.report.EmployeePerformanceReportDo$$EnhancerBySpringCGLIB$$20f266eb.listReport(<generated>)
	at com.newpearl.da.service.mvc.controller.DaEmployeeReportController.performance(DaEmployeeReportController.java:128)
	at com.newpearl.da.service.mvc.controller.DaEmployeeReportController$$FastClassBySpringCGLIB$$a82a6a.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685)
	at com.newpearl.da.service.mvc.controller.DaEmployeeReportController$$EnhancerBySpringCGLIB$$d68e9530.performance(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:893)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:798)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:665)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:94)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ArrayIndexOutOfBoundsException: null

This problem didn't appear in spring boot 1.x. it appeared after upgrading to microservice, spring boot 2.

Code

 List<DwOmEmployee> eeList = ees.getList();
        List<Future<DaEmployeePerformanceReportDto>> listfDto = new ArrayList<>();
        for (DwOmEmployee employee : eeList) {


            if (isDown){
                //When downloading, limit the current. Otherwise, there are too many asynchronous threads to request. Whether ES supports it or not, the connection pool is not enough
                rateLimiter.acquire();
            }

            // Get data of each employee asynchronously
            Future<DaEmployeePerformanceReportDto> fdto =
                    SpringUtils.getBean(this.getClass()).getAsyReportData(params, employee);



            listfDto.add(fdto);
        }

        List<DaEmployeePerformanceReportDto> listRdto = new ArrayList<>();

        //This kind of iterative method cannot be used for asynchronous multithreading. Because multithreading is asynchronous, spring extra processing is different
        for (Future<DaEmployeePerformanceReportDto> dtoFuture : listfDto) {
            listRdto.add(dtoFuture.get());
        }

It appears in this for each loop. It is generally known that if the list content changes during foreach execution, such as deletion and addition, it will appear: ArrayIndexOutOfBoundsException

That can only be done in iterator mode. This is what spring boot 2 does to its asynchrony

 

Iterator<Future<DaEmployeePerformanceReportDto>> it = listfDto.iterator();
        while(it.hasNext()){
            Future<DaEmployeePerformanceReportDto> x = it.next();
            listRdto.add(x.get());
        }

Change it to the above one, and you won't find this problem

 

summary

Try not to use asynchrony in concurrency. You need to consider whether a certain step of concurrent execution can be supported, such as the number of concurrent threads, whether the database connection pool is sufficient, and whether the concurrent amount of interface calls can be supported, etc

At the same time, asynchronous concurrent processing may cause some inexplicable problems

Posted by blacklotus on Sun, 05 Apr 2020 19:58:19 -0700