Java正则达式引起死循环问题解决办法

最近线上应用一直LOAD值非常高,几乎接近宕机的边缘,开始报异常如下:

at Java.util.regex.Pattern$GroupTail.match(Unknown Source)   at java.util.regex.Pattern$Ctype.match(Unknown Source)   at java.util.regex.Pattern$Branch.match(Unknown Source)   at java.util.regex.Pattern$GroupHead.match(Unknown Source)   at java.util.regex.Pattern$Loop.match(Unknown Source)   at java.util.regex.Pattern$GroupTail.match(Unknown Source)   at java.util.regex.Pattern$Ctype.match(Unknown Source)   at java.util.regex.Pattern$Branch.match(Unknown Source)   at java.util.regex.Pattern$GroupHead.match(Unknown Source)   at java.util.regex.Pattern$Loop.match(Unknown Source)   at java.util.regex.Pattern$GroupTail.match(Unknown Source)   at java.util.regex.Pattern$Ctype.match(Unknown Source)   at java.util.regex.Pattern$Branch.match(Unknown Source)   at java.util.regex.Pattern$GroupHead.match(Unknown Source)   at java.util.regex.Pattern$Loop.match(Unknown Source)   at java.util.regex.Pattern$GroupTail.match(Unknown Source)   at java.util.regex.Pattern$Ctype.match(Unknown Source)   at java.util.regex.Pattern$Branch.match(Unknown Source)   at java.util.regex.Pattern$GroupHead.match(Unknown Source)   at java.util.regex.Pattern$Loop.match(Unknown Source)   at java.util.regex.Pattern$GroupTail.match(Unknown Source)   at java.util.regex.Pattern$Ctype.match(Unknown Source)   at java.util.regex.Pattern$Branch.match(Unknown Source)  

通过异常信息抓取定位到我们的一个工具方法:该工具方法如下:

public static boolean checkSpecialChars(String inputstr, String regex)   {       if (inputstr == null || "".equals(inputstr))       {           return false;       }       return Pattern.compile(regex).matcher(inputstr).matches();   }  

没有任何地方是通过循环的调用本方法的,但根据异常信息很明显是死循环,这就引起我们进一步去跟踪问题,通过一段时间的测试和总结,终于找到问题的产生原因。该方法允许传一个正则表达式进去, 问题就出在传入的正则表达式上,该表达式简化为如下:

String regex = "([a-z]|//d)*";  

通过测试发现,此时若输入的字符串里面匹配次数超过817次以后,该方法将变的不稳定,开始重现我们前面的异常信息。测试代码如下:

import java.util.regex.Pattern;   /**   * Created on 2010-11-9   * <p>Title:       测试正则表达式死循环</p>   * @author         shixing_11@sina.com   * @version        1.0   */   public class RegexTest   {       public static void main(String args[])       {           String regex = "([a-z]|//d)*";           String inputStr = "";           for (int i = 0; i < 309; i++) //此处的值为>=400则会马上抛异常            {               inputStr = inputStr.concat(String.valueOf(i));  //循环的拼接输入字符串            }           System.out.println("字符串长度为:"+inputStr.length());           boolean flag = checkSpecialChars(inputStr, regex);           System.out.println("匹配结果为: "+flag);       }       public static boolean checkSpecialChars(String inputstr, String regex)       {           if (inputstr == null || "".equals(inputstr))           {               return false;           }           return Pattern.compile(regex).matcher(inputstr).matches(); //注意是此处matches()方法抛的异常        }   }  

原来:该问题是JDK的BUG,到JDK1.6里居然还没修复,BUG详情见:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wypwpg.html