首页

剖析java.lang.IllegalArgumentException: Illegal group reference异常原因

标签:IllegalArgumentException,异常,replaceAll,特殊字符     发布时间:2015-08-11   

一、问题现象

java.lang.IllegalArgumentException: Illegal group reference@b@    at java.util.regex.Matcher.appendReplacement(Matcher.java:713)@b@    at java.util.regex.Matcher.replaceAll(Matcher.java:813)@b@    at java.lang.String.replaceAll(String.java:2189)@b@    at com.xxx.search.sword.pu.org.AreaLeaveProcessUnit.reverseRemoveWords(AreaLeaveProcessUnit.java:47)@b@    at com.xxx.search.sword.pu.org.AreaLeaveProcessUnit.splitArea(AreaLeaveProcessUnit.java:66)@b@    at com.xxx.search.sword.pu.org.AreaLeaveProcessUnit.split(AreaLeaveProcessUnit.java:115)@b@    at com.xxx.search.sword.ISegment.split(ISegment.java:64)@b@    at com.xxx.search.sword.SegmentManager.split(SegmentManager.java:49)@b@    at com.xxx.fsearch.utest.action.UTestAction.swordQuery(UTestAction.java:69)@b@    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)@b@    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)@b@    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)@b@    at java.lang.reflect.Method.invoke(Method.java:597)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:450)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:289)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:252)@b@    at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:167)@b@    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)@b@  @b@  at @b@org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)@b@    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:239)@b@    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:239)@b@    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:252)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)@b@    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:239)@b@    at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:161)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189)@b@    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)@b@    at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)@b@    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:563)@b@    at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)@b@    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)@b@    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)@b@    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)@b@    at com.asc.sf.sec.SecurityFilter.doFilter(SecurityFilter.java:48)@b@    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)@b@    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:378)@b@    at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:99)@b@    at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)@b@    at org.springframework.security.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)@b@    at org.springframework.security.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)@b@    at org.springframework.security.ui.SessionFixationProtectionFilter.doFilterHttp(SessionFixationProtectionFilter.java:67)@b@    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)@b@    at org.springframework.security.ui.ExceptionTranslationFilter.doFilterHttp(ExceptionTranslationFilter.java:101)@b@    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)@b@  @b@  at @b@org.springframework.security.providers.anonymous.AnonymousProcessingFilter.doFilterHttp(AnonymousProcessingFilter.java:105)@b@    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)@b@    at org.springframework.security.ui.rememberme.RememberMeProcessingFilter.doFilterHttp(RememberMeProcessingFilter.java:116)@b@    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)@b@  @b@  at @b@org.springframework.security.wrapper.SecurityContextHolderAwareRequestFilter.doFilterHttp(SecurityContextHolderAwareRequestFilter.java:91)@b@    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)@b@    at org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:278)@b@    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)@b@    at org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89)@b@    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)@b@  @b@  at @b@org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)@b@    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)@b@    at org.springframework.security.concurrent.ConcurrentSessionFilter.doFilterHttp(ConcurrentSessionFilter.java:99)@b@    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)@b@    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)@b@    at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)@b@    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)@b@    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)@b@    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)@b@    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)@b@    at org.ajaxanywhere.AAFilter.doFilter(AAFilter.java:65)@b@    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)@b@    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)@b@    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)@b@    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)@b@    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)@b@    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)@b@    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)@b@    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)@b@    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)@b@    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)@b@    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)@b@    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)@b@    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)@b@    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)@b@    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)@b@    at java.lang.Thread.run(Thread.java:662)

二、模拟重现

示例代码,如下

public static void main(String[] args) {@b@        String  sk="$-$";@b@        String kk="123421".replaceAll("2", sk);@b@    }

运行结果,同样抛出java.lang.IllegalArgumentException: Illegal group reference异常

Exception in thread "main" java.lang.IllegalArgumentException: Illegal group reference@b@    at java.util.regex.Matcher.appendReplacement(Matcher.java:713)@b@    at java.util.regex.Matcher.replaceAll(Matcher.java:813)@b@    at java.lang.String.replaceAll(String.java:2189)@b@    at jh.modules.Java.main(Java.java:8)

三、解答原因

观察模拟重新代码运行的异常轨迹,可以判断是因为JDK提供java.util.regex.Matcher引起的,下面我们看下具体抛出异常的源码部分

/*      */   public Matcher appendReplacement(StringBuffer paramStringBuffer, String paramString)@b@/*      */   {@b@/*  691 */     if (this.first < 0) {@b@/*  692 */       throw new IllegalStateException("No match available");@b@/*      */     }@b@/*      */ @b@/*  695 */     int i = 0;@b@/*  696 */     String str = paramString;@b@/*  697 */     StringBuffer localStringBuffer = new StringBuffer();@b@/*      */ @b@/*  699 */     while (i < paramString.length()) {@b@/*  700 */       char c = paramString.charAt(i);@b@/*  701 */       if (c == '') {@b@/*  702 */         ++i;@b@/*  703 */         c = paramString.charAt(i);@b@/*  704 */         localStringBuffer.append(c);@b@/*  705 */         ++i;@b@/*  706 */       } else if (c == '$')@b@/*      */       {@b@/*  708 */         ++i;@b@/*      */ @b@/*  711 */         int j = paramString.charAt(i) - '0';@b@/*  712 */         if ((j < 0) || (j > 9)) {@b@/*  713 */           throw new IllegalArgumentException("Illegal group reference");@b@/*      */         }@b@/*  715 */         ++i;@b@/*      */ @b@/*  718 */         int k = 0;@b@/*  719 */         while (k == 0) {@b@/*  720 */           if (i >= paramString.length()) {@b@/*      */             break;@b@/*      */           }@b@/*  723 */           int l = paramString.charAt(i) - '0';@b@/*  724 */           if (l < 0) break; if (l > 9) {@b@/*      */             break;@b@/*      */           }@b@/*  727 */           int i1 = j * 10 + l;@b@/*  728 */           if (groupCount() < i1) {@b@/*  729 */             k = 1;@b@/*      */           } else {@b@/*  731 */             j = i1;@b@/*  732 */             ++i;@b@/*      */           }@b@/*      */ @b@/*      */         }@b@/*      */ @b@/*  737 */         if (group(j) != null)@b@/*  738 */           localStringBuffer.append(group(j));@b@/*      */       } else {@b@/*  740 */         localStringBuffer.append(c);@b@/*  741 */         ++i;@b@/*      */       }@b@/*      */ @b@/*      */     }@b@/*      */ @b@/*  746 */     paramStringBuffer.append(getSubSequence(this.lastAppendPosition, this.first));@b@/*      */ @b@/*  748 */     paramStringBuffer.append(localStringBuffer.toString());@b@/*      */ @b@/*  750 */     this.lastAppendPosition = this.last;@b@/*  751 */     return this;@b@/*      */   }

通过上面源码,我们可以清楚的看出第713行抛出了问题异常,在向上第706行查看执行该逻辑的前提条件 -被替换的字符中包含有'$',回到模拟重现代码中String  sk="$-$";所以我们找到问题的答案,被替换的字符中不能包含特殊字符'$'