为什么填充数组的代码会造成内存泄漏?

时间:2011-02-16 13:19:26

标签: java arrays dynamic memory-leaks

我在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被初始化为Array的{​​{1}}

Object

Object[] entries = null ; 是要添加的addition(作为参数传递给此代码所在的方法)。


代码通过编译器但在调用时会导致内存泄漏。我能够将原因缩小到代码尝试填充新Object

的行
Array

然而,我想不出有什么理由会导致内存泄漏。我猜测问题的根源必须是我自己的一个非常愚蠢的错误,或者是一个非常棘手的Java问题。 :-)

如果您需要更多背景,请告诉我。

修改

Tomcat的日志告诉我:

  

Web应用程序似乎已启动名为...的线程但未能将其停止。   这很可能会造成内存泄漏。

除此之外,显然加载类的页面没有完成加载或加载非常缓慢。

修改

问题可能在其他地方(在更加预期的位置)。显然当我试图确定错误的代码时,Tomcat并没有一直加载类文件,这让我误解了一下。我现在怀疑一个infinte for-each循环是由于调用堆栈中有缺陷的Iterator实现导致的。 无论如何,感谢您的投入!总是非常感激!


我将使用 entries[i] = entry ; (可能是Collection)代替Vector作为解决方法;不过,我想知道这里的问题是什么。

TIA,

FK82

4 个答案:

答案 0 :(得分:3)

所以,关于你的Tomcat日志消息:

  

Web应用程序似乎已启动名为...的线程但未能将其停止。这很可能会造成内存泄漏。

这表示你的servlet或类似的东西启动了一个新线程,当你的servlet完成它的操作时,这个线程仍在运行。它与您的示例代码完全无关(如果此代码不是启动该代码的代码)。

多余的线程,甚至更多的每个HTTP请求启动一个新的(不会很快完成)可能会造成内存泄漏,因为每个线程需要相当大的空间用于其堆栈,并且还可能通过引用来禁止垃圾收集不再需要的物体。确保你的线程确实需要,并考虑使用线程池(最好是容器管理的,如果可能的话)。

答案 1 :(得分: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建议的阵列复制方法。

将这篇文章视为评论。我刚发布它作为答案,因为我不知道代码在评论中的格式是什么......

答案 2 :(得分: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]);

 }

}

答案 3 :(得分:1)

也许是因为Memory Leak你意味着OutOfMemoryException?有些时候,如果你没有在启动时将最小堆大小设置得足够高(并且也是一个定义良好的最大堆大小),那么你可以在Java中得到它。如果在启动时没有创建足够的堆,那么有时可以比JVM有时间将更多内存分配给堆或垃圾收集更快地使用它。不幸的是,这里没有“正确答案”。您只需要使用不同的设置来获得正确的结果(即,称为“调整JVM”)。换句话说,这更像是一门艺术,而不是一门科学。

如果您不知道,在启动程序时将参数传递给命令行上的JVM -Xmin 250m -Xmax 1024m就是一个例子。您必须以兆字节为单位指定值。第一个将最小堆(启动时)设置为250兆字节。第二个参数将最大堆大小设置为1千兆字节。

只是另一个想法,因为我也很困惑你如何将内存泄漏跟踪到一行代码。