2011-02-16 51 views
0

我在使用Java動態填充數組這一簡單任務時遇到了一個有些莫名其妙的問題。以下是從哪裏的問題起源的快照:爲什麼此代碼填充數組會造成內存泄漏?

entries = new Object[ (n = _entries.length + 1) ] ; 

for(i = 0 ; i < n ; i++) { 

      entry = (i == (n - 1)) ? addition : _entries[i] ; 

      entries[i] = entry ; 

      //... 

} 

_entries是源Array(類的字段); entries被初始化爲一個ArrayObject小號

Object[] entries = null ; 

addition和要被添加的Object(作爲參數傳遞給該代碼是在該方法中傳遞)。


代碼通過編譯器,但調用時會導致內存泄漏。我能事業縮小到所在行的代碼試圖填補新Array

entries[i] = entry ; 

不過,我想不出任何理由爲什麼這會導致內存泄漏。我猜測問題的根源必須是我的一個非常愚蠢的錯誤,或者Java的一個非常神祕的問題。 :-)

如果您需要更多背景,請告訴我。

編輯:

Tomcat的日誌告訴我:

Web應用程序似乎已經開始了一個名爲線程...但未能阻止它。 這很可能會造成內存泄漏。

除此之外,顯然加載類的頁面並未完成加載或加載非常緩慢。

編輯:畢竟

這個問題可能在其他地方(在更期望的位置)。顯然,當我試圖鎖定有問題的代碼時,Tomcat並沒有一直加載類文件,這會誤導我一點。我現在懷疑由於在調用堆棧中存在有缺陷的Iterator實現而造成的每個循環都會導致一個infinte錯誤。 無論如何,感謝您的輸入!總是非常感謝!


我會用一個Collection(可能是一個Vector)而不是Array作爲一個變通;仍然,我想知道這裏的問題是什麼。

TIA,

FK82

+3

Off topic:$條目是什麼意思?在java中,我從來沒有在這個上下文中看到$ notation。有人能爲此啓發我嗎? – 2011-02-16 13:22:25

+0

@shadow:那也讓我感到困惑。我想這是一種代碼模板機制。 – 2011-02-16 13:23:16

+4

是什麼讓你覺得有內存泄漏?這在Java中很難做到。 – Gabe 2011-02-16 13:23:27

回答

1

我看不到內存泄漏,但你的代碼複雜得多,它需要的。這個怎麼樣:

newLength = $entries.length + 1; 
entries = new Object[ newLength ] ; 

for(i = 0 ; i < newLength - 1 ; i++) { 
     entries[i] = $entries[i]; 
     //... 
} 

entries[ newLength - 1 ] = addition; 

不需要檢查你是否一直在最後一個條目,你可以使用Alison建議的數組複製方法。

將此貼作爲評論。我剛剛張貼作爲一個答案,因爲我不知道代碼是如何在評論格式...

1

這是爲我工作,

請找到示例代碼。並相應地更改它

class test { 

public static void main(String[] args) { 


    String[] str = new String[]{"1","2","3","4","5","6"}; 

    int n=0; 
    Object[] entries = new Object[ (n = 5 + 1) ] ; 

    for(int i = 0 ; i < n ; i++) { 

      Object entry = (i == (n - 1)) ? new Object() : str [i] ; 

      entries[i] = entry ; 



    } 
    System.out.println(entries[3]); 

} 

} 
1

也許通過內存泄漏你意味着一個OutOfMemoryException?有時候,如果您在啓動時沒有將最小堆大小設置得足夠高(以及定義的最大堆大小),則可以通過Java獲得。如果在啓動時沒有創建足夠的堆,那麼您有時可以更快地使用它,這比JVM有時間將更多的內存分配給堆或垃圾收集更快。不幸的是,這裏沒有「正確答案」。你只需要使用不同的設置來獲得正確的結果(即,稱爲「調整JVM」)。換句話說,這更像是一門藝術而不是科學。

如果您不知道,在啓動程序時,將命令行參數傳遞給JVM -Xmin 250m -Xmax 1024m就是一個例子。您必須以兆字節爲單位指定值。第一個設置最小堆(啓動時)爲250兆字節。第二個參數將最大堆大小設置爲1千兆字節。

只是另一個想法,因爲我也爲你如何跟蹤內存泄漏到一行代碼而感到困惑。

3

所以,關於你的Tomcat的日誌消息:

Web應用程序似乎已經開始了一個名爲線程...但未能阻止它。這很可能造成內存泄漏。

這就是說你的servlet或類似的東西啓動了一個新的線程,並且當你的servlet完成它的操作時這個線程仍然在運行。它完全不涉及你的示例代碼(如果這個代碼不是啓動線程的代碼)。

當每個HTTP請求啓動一個新的HTTP請求(它不會很快完成)時,更多的線程可能會創建內存泄漏,因爲每個線程都需要一定的空間來存放堆棧,並且還可能會阻止垃圾收集。引用不再需要的對象。確保你的線程真的需要,並考慮使用線程池(最好是容器管理,如果這是可能的話)。