1. 程式人生 > >正則表示式二次Matcher.find時 java.lang.StackOverflowError的解決方法

正則表示式二次Matcher.find時 java.lang.StackOverflowError的解決方法

在最近一個java專案中使用了正則表示式,抓取網頁中的內容,明明很正確的正則表示式,但在Matcher.find時報錯了:

    public static List<String> findStrs(String regx,String sourceStr){
        Pattern pattern = Pattern.compile(regx);
        Matcher m = pattern.matcher(sourceStr);
        List<String> result=new ArrayList<>();
        while (m.find()) {
            result.add(m.group(1));
        }
        return result.size()<=0?null:result;
    }

後來單步除錯,發現在第一次find時正確獲取到,第二次報錯了,錯誤是:

java.lang.StackOverflowError
	at java.lang.String.charAt(String.java:657)
	at java.util.regex.Pattern$Slice.match(Pattern.java:3971)
	at java.util.regex.Pattern$LazyLoop.match(Pattern.java:4845)
	at java.util.regex.Pattern$GroupTail.match(Pattern.java:4719)
	at java.util.regex.Pattern$BranchConn.match(Pattern.java:4570)
	at java.util.regex.Pattern$CharProperty.match(Pattern.java:3779)
	at java.util.regex.Pattern$Branch.match(Pattern.java:4606)
	at java.util.regex.Pattern$GroupHead.match(Pattern.java:4660)
	at java.util.regex.Pattern$LazyLoop.match(Pattern.java:4849)
	at java.util.regex.Pattern$GroupTail.match(Pattern.java:4719)
	at java.util.regex.Pattern$BranchConn.match(Pattern.java:4570)
	at java.util.regex.Pattern$CharProperty.match(Pattern.java:3779)
	at java.util.regex.Pattern$Branch.match(Pattern.java:4606)
	at java.util.regex.Pattern$GroupHead.match(Pattern.java:4660)
	at java.util.regex.Pattern$LazyLoop.match(Pattern.java:4849)
	at java.util.regex.Pattern$GroupTail.match(Pattern.java:4719)
	at java.util.regex.Pattern$BranchConn.match(Pattern.java:4570)
	at java.util.regex.Pattern$CharProperty.match(Pattern.java:3779)
	at java.util.regex.Pattern$Branch.match(Pattern.java:4606)
	at java.util.regex.Pattern$GroupHead.match(Pattern.java:4660)
	at java.util.regex.Pattern$LazyLoop.match(Pattern.java:4849)
	at java.util.regex.Pattern$GroupTail.match(Pattern.java:4719)
	at java.util.regex.Pattern$BranchConn.match(Pattern.java:4570)
	at java.util.regex.Pattern$CharProperty.match(Pattern.java:3779)
	at java.util.regex.Pattern$Branch.match(Pattern.java:4606)
	at java.util.regex.Pattern$GroupHead.match(Pattern.java:4660)
	at java.util.regex.Pattern$LazyLoop.match(Pattern.java:4849)
	at java.util.regex.Pattern$GroupTail.match(Pattern.java:4719)
	at java.util.regex.Pattern$BranchConn.match(Pattern.java:4570)
	at java.util.regex.Pattern$CharProperty.match(Pattern.java:3779)
	at java.util.regex.Pattern$Branch.match(Pattern.java:4606)
	at java.util.regex.Pattern$GroupHead.match(Pattern.java:4660)
	at java.util.regex.Pattern$LazyLoop.match(Pattern.java:4849)
... ...

在網上查了下,發現問題是棧溢位,有人給出瞭解決方法:

Pattern   pattern   =   Pattern.compile(re,Pattern.DOTALL   +   Pattern.MULTILINE);

其中Pattern.DOTALL   +   Pattern.MULTILINE指,在正則表示式中的:.可以代替所有字元,包括換行符\n。原先的寫法可能是:xxx(?:\n|.)*?xxx,現在可以寫成xxx.*?xxx,。

使用這個方法,問題暫時解決。但問題原理 不明,可能是sdk的bug吧。

注:此方法可以避免此問題,但附帶的,因為在使用.時,忽略了換行,可能使用正則表示式匹配到更大範圍的內容,所以寫正則時需要格外小心。另外,後來我試了一下,只要在匹配時少於二個換行的內容,不使用此方法,也可以正常執行,所以感覺在java中使用正則表示式時,儘量的匹配少量的內容,就不會出錯了。