如何中断一个长时间运行的”无限”Java正则表达式
来源:互联网 发布:网络商标注册费用 编辑:程序博客网 时间:2024/04/28 15:35
本文由 ImportNew - 人晓 翻译自 ocpsoft。欢迎加入Java小组。转载请参见文章末尾的要求。
如果你处理过大量的正则表达式,那么你对“catastrophic backtracking”的概念一定不陌生,这种情况下处理器被强迫执行指数倍的计算。例如,点击该示例,看看它需要多久完成(应该在5-10秒后超时)。
LongRunningRegexExample.java
01
public
class
LongRunningRegexExample
02
{
03
public
static
void
main(String[] args)
throws
InterruptedException
04
{
05
final
Pattern pattern = Pattern.compile(
"(0*)*A"
);
06
final
String input =
"00000000000000000000000000"
;
07
08
long
startTime = System.currentTimeMillis();
09
Matcher matcher = pattern.matcher(input);
10
matcher.find();
// runs for a long time!
11
System.out.println(
"Regex took:"
+ (System.currentTimeMillis() - startTime) +
"ms"
);
12
}
13
}
但是,小小的改动就能让该程序立即响应。为什么呢?这里引用Dzone中Andreas Haufler的文章《How to Kill Java with a Regular Expression》,其中提到了这个非常简洁的例子:
- 第一眼看上去像是无限循环的东西会造成catastrophic backtracking
- 意思是说匹配器在输入的末尾并没有检测到”A”。现在外侧的限定符后退一次,内存的则前进一次,如此重复,无法得到结果。
- 因此,匹配器逐步回退,并尝试所有的组合以找出匹配符号。它最终将返回(没有匹配的结果),但是该过程的复杂性是指数型的(输入中添加一个字符加倍了运行时间)。
所以,我们究竟该采取何种方式避免这种破坏性的影响,我们是否会遇到Java程序运行数天甚至几年的情形?
在你的资源非常充足的情况下,你也许可以简单小心的在你的模式中避免这种情况。但是,如果你正在开发一个接受正则表达式作为输入的应用程序,例如一个在线Java可视化的正则表达式示例,那么你就应该避免这种情情况或是受到拒绝服务器攻击。
幸运的是,答案非常简单,但需要引入一个线程,以及一个非常特殊的字符串序列。我是在StackOverflow上找到该实现的。
InterruptibleRegexExample.java
01
public
class
InterruptibleRegexExample
02
{
03
public
static
void
main(String[] args)
throws
InterruptedException
04
{
05
final
Pattern pattern = Pattern.compile(
"(0*)*A"
);
06
final
String input =
"00000000000000000000000000"
;
07
Runnable runnable =
new
Runnable() {
08
@Override
09
public
void
run()
10
{
11
long
startTime = System.currentTimeMillis();
12
Matcher interruptableMatcher = pattern.matcher(
new
InterruptibleCharSequence(input));
13
interruptableMatcher.find();
// runs for a long time!
14
System.out.println(
"Regex took:"
+ (System.currentTimeMillis() - startTime) +
"ms"
);
15
}
16
};
17
18
Thread thread =
new
Thread(runnable);
19
thread.start();
20
21
Thread.sleep(
500
);
22
thread.interrupt();
23
}
24
}
结果很好的中断了正则表达式:
Exception in thread “Thread-2″ java.lang.RuntimeException: Die! … Why won’t you DIE!at org.ocpsoft.tutorial.regex.server.InterruptRegex$InterruptibleCharSequence.charAt(InterruptRegex.java:72)
at java.util.regex.Pattern$BmpCharProperty.match(Pattern.java:3366)
at java.util.regex.Pattern$Curly.match0(Pattern.java:3760)
at java.util.regex.Pattern$Curly.match(Pattern.java:3744)
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4168)
你还需要一个InterruptibleCharSequence类,它在某种程度上也会影响性能,但是要比等上一年要好的多:
InterruptibleCharSequence.java
01
/**
02
* {@link CharSequence} that notices {@link Thread} interrupts
03
*
04
* @author gojomo
05
*/
06
private
static
class
InterruptibleCharSequence
implements
CharSequence {
07
CharSequence inner;
08
public
InterruptibleCharSequence(CharSequence inner) {
09
super
();
10
this
.inner = inner;
11
}
12
13
@Override
14
public
char
charAt(
int
index) {
15
if
(Thread.currentThread().isInterrupted()) {
16
throw
new
RuntimeException(
"Interrupted!"
);
17
}
18
return
inner.charAt(index);
19
}
20
21
@Override
22
public
int
length() {
23
return
inner.length();
24
}
25
26
@Override
27
public
CharSequence subSequence(
int
start,
int
end) {
28
return
new
InterruptibleCharSequence(inner.subSequence(start, end));
29
}
30
31
@Override
32
public
String toString() {
33
return
inner.toString();
34
}
35
}
结论
我很开心能学习并撰写这些内容,这篇博客总结了正则表达式的无限运行及解决方案(Java中),希望它能帮到其他遇到该问题的人。愉快的过程!
原文链接: ocpsoft 翻译: ImportNew.com - 人晓
译文链接: http://www.importnew.com/11975.html
- 如何中断一个长时间运行的”无限”Java正则表达式
- 如何中断一个正在运行的线程
- Java中断一个正在运行的线程
- 一个简单的java正则表达式例子
- java 正则表达式的一个理解.
- java正则表达式的一个例子
- 一个java正则表达式的小例子
- 如何使用java的正则表达式
- Java怎样中断一个运行中的线程
- Java怎样中断一个运行中的线程
- Unity中如何中断C#脚本的无限循环
- Java如何使用正则表达式。
- 查看长时间运行的session
- Java的正则表达式
- Java的正则表达式
- java的正则表达式
- java的正则表达式
- Java的正则表达式
- 理解RESTful架构
- node.js-<一>安装运行第一个程序
- 生成批量附加数据库语句
- Java初学习 - Collections.unmodifiableList方法的使用与场景
- java Class类详解
- 如何中断一个长时间运行的”无限”Java正则表达式
- 非递归的 MergeSort
- C#收发HttpWebResponse(3)——Json
- 【cocos2dx学习笔记】移植到安卓平台
- apache 之 you don't have permission to access / on this server linux 下 错误解决方法
- 第十三周项目六——体验文件操作(3-实战)
- JDBC Performance Tips – 4 Tips to improve performance of Java application with database
- 第13周项目4-冒泡法排序
- 【Android 开发】: Android 消息处理机制之三: Handler 中 sendMessage() 源代码剖析