2011-02-16 52 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请求(它不会很快完成)时,更多的线程可能会创建内存泄漏,因为每个线程都需要一定的空间来存放堆栈,并且还可能会阻止垃圾收集。引用不再需要的对象。确保你的线程真的需要,并考虑使用线程池(最好是容器管理,如果这是可能的话)。