Alex Rivera | Logout

Java regular expression optimization tips

Asked 2011-09-30T07:31:51.223
11

I am new to Java Regular expression. We are using a pattern for matching a string. We are using this for validating a text field and it meets our requirements. But there is a performance issue in the matching.

Pattern : ([a-zA-Z0-9]+[ ]?(([_\-][a-zA-Z0-9 ])*)?[_\-]?)+

  1. Input text should start with a-zA-Z0-9.
  2. Space(single) is allowed between words
  3. "_" and "-" are allowed but cannot be consecutive.

Our problem is, for certain input strings the CPU time goes high and causes hanging the threads. Also we get exceptions. Can anyone please help me to optimize the Pattern or suggest a new pattern to solve my issue.

Exception details                              
============================================                           
Hung thread details, all the same:
[9/28/11 11:40:07:320 CDT] 00000003 ThreadMonitor W   WSVR0605W: Thread "WebContainer : 26" (0000004f) has been active for 709755 mi
lliseconds and may be hung.  There is/are 1 thread(s) in total in the server that may be hung.
        at java.util.regex.Pattern$GroupCurly.match(Pattern.java:3938)
        at java.util.regex.Pattern$GroupHead.match(Pattern.java:4180)
        at java.util.regex.Pattern$Branch.match(Pattern.java:4124)
        at java.util.regex.Pattern$Ques.match(Pattern.java:3703)
        at java.util.regex.Pattern$Curly.match0(Pattern.java:3801)
        at java.util.regex.Pattern$Curly.match(Pattern.java:3756)
        at java.util.regex.Pattern$GroupHead.match(Pattern.java:4180)
        at java.util.regex.Pattern$Loop.match(Pattern.java:4307)
        at java.util.regex.Pattern$GroupTail.match(Pattern.java:4239)
        at java.util.regex.Pattern$Ques.match(Pattern.java:3703)
        at java.util.regex.Pattern$BranchConn.match(Pattern.java:4090)
        at java.util.regex.Pattern$GroupTail.match(Pattern.java:4239)
        at java.util.regex.Pattern$GroupCurly.match0(Pattern.java:4006)
        at java.util.regex.
Edit
Report

2 Answers

2

I wanted to post this as a comment to Tim Pietzcker's answer but figured there won't be enough space there. While the regex given by Tim avoids catastrophic backtracking to some extent, it still has nested quantifiers which can cause a problem with a specific input text and cause StackOverflowException as shown below. I want to repeat that this answer is just a demonstration of the weird StackOverflowException and it is not supposed to be a rant on anyone's answer.

    public class CatastrophicBacktrackingRegexRemedy {
    public static void main(String[] args) {
        regexWithNoStackOverflow();
        regexCausingStackOverflow();
    }

    /**
     * Stackoverflow is caused on a specific input, 
     * In this case "A " repeated about 1000 times.
     * This is because of the nested quantifier (?:[\\ ][\\w-]+)*
     */
    private static void regexCausingStackOverflow() {
        StringBuilder subjectStringBuilder = new StringBuilder();
        String subjectString = "A ";
        for (int i = 0; i < 1000; i++) {
            subjectStringBuilder.append(subjectString);
        }
        subjectStringBuilder.append("A");
        //2001 character input
        System.out.println("Input length :" + subjectStringBuilder.length());
        //This causes stackoverflow exception on a string with 2001 characters 
        //on my JVM
        boolean foundMatch = subjectStringBuilder.toString().matches(
                "(?ix)        # Case-insensitive, multiline regex:\n"
                + "^          # Start of string\n"
                + "(?!        # Assert that it's impossible to match\n"
                + " .*        # any number of characters\n"
                + " (?:--|__) # followed by -- or __\n"
                + ")          # End of lookahead assertion\n"
                + "[A-Z0-9]+  # Match A-Z, a-z or 0-9\n"
                + "(?:        # Match the following:\n"
                + " [\\ ]     # a single space\n"
                + " [\
answered 2011-09-30T14:03:16.350
0

You haven't posted any code but I can see that you run it in a web application. I guess optimization of the pattern won't help you much. Remember that the Matcher class is not thread safe.

Instances of this class are not safe for use by multiple concurrent threads

Try to compile your pattern in synchronized block and use reset() method of the Matcher class.

answered 2011-09-30T07:44:00.920

Your Answer