我正在開發一個我必須在Android中管理的數百個正則表達式的測試。 我遇到了一個災難性的回溯,我無法阻止,(即匹配器進入指數複雜度,它似乎處於無限循環中,而實際上,它正在探索非常多的可能匹配),所以我需要使用超時限制匹配的整體執行。避免由Android中的Java代碼生成的JNI錯誤
我已經找到了一個可能的方法here,但我也必須從find()方法獲得布爾返回值,所以Runnable不是最好的選擇。 即使在上面的鏈接中的其他答案中提出的小變化,以避免使用線程是不適用的,因爲它基於CharSequence的擴展,它根本不工作,因爲charAt沒有用在matcher.find ()(檢查了兩次,在調試過程中都帶有斷點,並且還讀取了Matcher源代碼)。 編輯:我在第二次發現,還@NullPointerException already found了的charAt得到從來沒有所謂,但我不知道是否因爲3年前,他找到了一個解決方案
所以,最好的選擇我發現直到現在似乎正在使用FutureTask,它有可能指定一個超時,並且還可以返回一個值。我執行下面的代碼:
private boolean interruptMatch(final Matcher matcher){
boolean res = false;
ExecutorService executor = Executors.newSingleThreadExecutor();
FutureTask<Boolean> future =
new FutureTask(new Callable() {
public Boolean call() {
return matcher.find();
}
});
executor.execute(future);
try {
res = future.get(2000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Log.d("TESTER","Find interrupted after 2000 ms");
} catch (ExecutionException e) {
Log.d("TESTER","Find ExecException after 2000 ms");
} catch (TimeoutException e) {
Log.d("TESTER","Find timeout after 2000 ms");
}
future.cancel(true);
executor.shutdownNow();
return res;
}
這部分代碼是由主要方法調用,在一個幾乎「經典」的方式:
pattern = Pattern.compile(pattern, java.util.regex.Pattern.CASE_INSENSITIVE);
matcher = pattern.matcher(inputString);
if (interruptMatch(matcher)) { // before the need to manage catastrophic backtracking here there was a simple if (matcher.find()){
// Do something
}
所以,萬物似乎工作,至少對第一幾百模式(也限制超時時間災難性回溯長期運行發現),直到我得到了以下錯誤:
JNI錯誤(應用程序錯誤):弱全局引用表溢出(最大值= 51200)
它已經由上面的java代碼生成了(在此錯誤沒有出現之前 - 顯然取消導致災難性回溯的模式),但是我找不到如何清除全局引用表(我發現關於由JNi代碼直接生成但不是來自Java的類似問題的許多答案),而不是如何找到解決方法或其他有效方法。 編輯:我進一步嘗試調試,發現問題出現在我調用get方法時。我試圖遵循FutureTask的代碼,但我沒有發現任何有用的東西(而且我感到無聊得太快)。
你能幫助我嗎? 謝謝你提前