我在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
答案 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千兆字节。
只是另一个想法,因为我也很困惑你如何将内存泄漏跟踪到一行代码。