2009-06-11 95 views
3

我正在嘗試編寫一個junit測試來防止一段代碼陷入無盡的迭代,最終會導致StackOverflow。在Java中減少運行時的最大堆棧大小

所以我正在尋找一種方法來減少在運行時的堆棧大小,所以Junittest將失敗得更快。

將max stack設置爲jvm參數是不可能的,因爲測試是一個更大的測試套件的一部分。

回答

5

您可以運行,這將運行本身的給定次數,然後遞歸方法執行給定的操作。聽起來很酥雖然:(

喜歡的東西:

public void eatStackThenExecute(int depth, Runnable action) 
{ 
    // Maybe put some locals here (and use them) to eat more stack per iteration? 
    if (depth == 0) 
    { 
     action(); 
    } 
    else 
    { 
     eatStackThenExecute(depth - 1, action); 
    } 
} 

編輯:這可能是聰明的JVM會在這裏優化尾調用,所以它可能是我們需要後做「事」遞歸調用阻止這樣的事情發生......

伊克「東經東西:(

+0

哇。多麼可怕的想法。但實際上,它確實將堆棧深度設置爲JVM的最大值 - 運行時的深度精度,因此無論如何+1。 – 2009-06-11 15:10:33

2

它無法在運行時設置堆棧大小,但也許你可以:

  • 調用不同的線程內部的一段代碼 - 保留對它的引用;
  • 定期輪詢thread.getStackTrace(),如果其大小大於x,則失敗;
  • 如果執行正確終止,則取消檢查。的概念代碼

未編譯證明(不正確地檢查所有的邊界條件):

AtomicBoolean success = new AtomicBoolean(false); 

Thread t= new Thread(new Runnable() { 
    public void run() { 
     codeToTest(); 
     success.set(true); 
    } 

}); 

t.start(); 

while (t.isAlive()) { 
    if (t.getStackTrace().length > 50) 
      fail("Stack trace too large"); 

    Thread.sleep(50); 
} 

assertTrue(sucess.get()); 
1

你可以這樣才設置參數在啓動時,但你可以開始從Java另一個進程。所以,你可以讓你的單元測試以較小的堆棧大小開始第二個進程改變你的測試。

+0

應該由「進程」第一個「進展」? – 2012-10-16 17:44:18

+0

@MattFenwick是的,謝謝。 – 2012-10-16 21:08:27

0

這有點......好,有趣......但它可能是值得的。

  1. 取出.class文件並用jasper反編譯。
  2. 編輯生成的JVM程序集代碼並添加或更改要以此方式測試的例程的「.limit stack x」參數。
  3. Jasmin重新編譯。
  4. 運行並測試。