2016-12-04 66 views
0

我正在開發一個我必須在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的代碼,但我沒有發現任何有用的東西(而且我感到無聊得太快)。

你能幫助我嗎? 謝謝你提前

回答

0

經過其他挖掘後,我發現在Android中有一個tracked issue(它似乎它處理其他主題,但它也回答我的),並從答覆我明白,這只是一個問題在調試期間出現。我再次測試了我的測試程序,發現它是真的:沒有調試上述錯誤不會發生。所以,問題的嚴重程度要低得多,我可以忍受它(對我來說這是一個封閉的問題) -