加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_开封站长网 (http://www.0378zz.com/)- 科技、AI行业应用、媒体智能、低代码、办公协同!
当前位置: 首页 > 教程 > 正文

Java正则达式引起死循环问题解决措施

发布时间:2021-12-18 17:02:54 所属栏目:教程 来源:互联网
导读:最近线上应用一直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

最近线上应用一直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()方法抛的异常   
    }  
}  
 
通过上面方法解决上抛异常问题,修改完机器重启后发现异常是不抛了,但CPU占用率高并没有好转,频频报警,经过仔细排查,有五个处理正则的线程把CPU资源耗完了,实在没招,最后校验采用其它方法,彻底干掉正则。
 
总结:通过这次线上问题排查,正则表达式是个双仞剑,如果大规模数据的校验最好不要使用正则,效率非常差。CPU的处理能力会全部耗费在处理这几个正则上。另外该问题是项目上线一段时间后才出现,这说明当数据达到一个数量级后,正则的处理效率会快速下降,这样就像我这种情况,刚开始数据量小,一直没有问题,等到访问量突然增大后,CPU在短时间内LOAD值非常高。所以正则轻易不要���在大数据量或者并发访问较高的应用中。

(编辑:开发网_开封站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读