java.lang.StackOverflowError,同时使用正则表达式来解析大字符串

2022-09-01 00:26:27

这是我的正则表达式

((?:(?:'[^']*')|[^;])*)[;]

它对分号上的字符串进行标记。例如

Hello world; I am having a problem; using regex;

结果是三个字符串

Hello world
I am having a problem
using regex

但是当我使用一个大的输入字符串时,我得到这个错误

Exception in thread "main" java.lang.StackOverflowError
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4168)
at java.util.regex.Pattern$Loop.match(Pattern.java:4295)
at java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)
at java.util.regex.Pattern$BranchConn.match(Pattern.java:4078)
at java.util.regex.Pattern$CharProperty.match(Pattern.java:3345)
at java.util.regex.Pattern$Branch.match(Pattern.java:4114)
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4168)
at java.util.regex.Pattern$Loop.match(Pattern.java:4295)
at java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)

这是如何引起的,我该如何解决?


答案 1

不幸的是,Java的内置正则表达式支持存在包含重复替代路径(即)的正则表达式问题。这会编译为递归调用,当用于非常大的字符串时,这会导致 StackOverflow 错误。(A|B)*

一个可能的解决方案是重写你的正则表达式,不使用重复的替代项,但是如果你的目标是在分号上标记字符串,你根本不需要一个复杂的正则表达式,只需使用String.split()和一个简单的参数。";"


答案 2

如果你真的需要使用一个溢出你的堆栈的正则表达式,你可以通过将类似 -Xss40m 的东西传递给 JVM 来增加堆栈的大小。