编辑: 没有内存泄漏,只是对Netbeans Profiler告诉我的内容有点误解。实时分析结果 - >分配的对象是指在程序的生命周期内分配的TOTAL,而不是当前在内存中的总数。为此,获取堆转储。很抱歉这个混乱,但也许其他人会发现这一点,它会清除它们。
我使用NetBeans 7.0.1分析器来解决应用程序中的内存增长问题,并且看到了两个主要问题。我已经成功创建了测试应用程序,并在分析器中看到了相同的结果,如下所示。我无法在其他地方找到对这些的引用。
案例1:循环访问HashMap的入口集导致对象java.util.HashMap& EntryIterator增长。除了找出一个不同容器的解决方案之外,这里有什么可做的吗?每次在while循环中循环遍历集合对于我们的应用程序是必要的。
public static void main(String[] args) throws InterruptedException {
boolean run = true;
HashMap<Integer, Integer> map = new HashMap<Integer, Integer> ();
map.put(1, 2);map.put(3, 4);map.put(5, 6);map.put(7, 8);
while(true){
for (Entry<Integer, Integer> entry : map.entrySet()) {
Integer i = entry.getValue();
}
//app specific code here
Thread.sleep(50);
}
}
案例2:在循环中创建空ArrayLists会导致java.lang.Object []的增长。我希望ArrayLists在while循环结束时符合GC的条件。我的假设错了吗?或者还有什么在这里发挥作用?
public static void main(String[] args) throws InterruptedException {
boolean run = true;
while(run){
ArrayList<Integer> a1 = new ArrayList<Integer>();
ArrayList<Integer> a2 = new ArrayList<Integer>();
// app specific code here
Thread.sleep(50);
}
}
答案 0 :(得分:2)
我认为这两个代码示例都没有泄漏内存。您必须确保区分“堆增长直到垃圾收集器运行”和“堆永远增长”。如果您删除Thread.sleep调用并永久运行任一应用程序,它不应该崩溃,并且随着垃圾收集器运行,JVM的堆使用率应该上升和下降。您可以尝试在每个循环期间运行“System.gc()”并查看您的探查器是否仍显示泄漏。
答案 1 :(得分:0)
只要没有其他代码引用GC,您的第二个示例中的ArrayLists就有资格使用GC。此外,您无法控制执行垃圾收集的方式和时间。你知道你在使用什么垃圾收集器吗?你用任何特定的vm标志运行程序吗?在调用System.gc以强制进行垃圾回收后,您是否遇到过奇怪的行为?您的应用特定代码是否引用了您的数组列表?
答案 2 :(得分:0)
在你的两个示例方法中,即使GC运行它也不能声明这些对象。
即使您的对象在循环外被初始化,然后在某些编译器上,字节码与在循环内创建的字节码相同,也没有太大区别。
此外,您不能保证GC是否会运行并且您的对象将被回收。
编辑:
SO上的类似帖子
答案 3 :(得分:0)
虽然我找不到任何令人不安的内容,但我只是尝试了两个代码段。我删除了sleep
以加快测试速度。垃圾收集器每秒工作几次疯狂,基本上清理整个年轻一代(尝试使用-XX:+PrintGCDetails -XX:+PrintGCTimeStamps
):
[GC [PSYoungGen: 104272K->0K(99712K)] 105235K->963K(131968K), 0.0008090 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
代码运行几分钟,CPU利用率非常高,但内存使用率稳定。两个代码示例中肯定存在无内存泄漏。
你可能观察到的是堆的增量增长(JVM中的年轻代基本上是一个堆栈,在彼此之上分配新对象而不用担心垃圾)。垃圾收集在堆栈耗尽时运行。
答案 4 :(得分:0)
你所说的很多内容取决于:
// app specific code here
你在这里做的事情可能会影响垃圾收集。对于您发布的代码,这将导致内存泄漏。例如,每次通过这个循环:
public static void main(String[] args) throws InterruptedException {
boolean run = true;
while(run){
ArrayList<Integer> a1 = new ArrayList<Integer>();
ArrayList<Integer> a2 = new ArrayList<Integer>();
// app specific code here
Thread.sleep(50);
}
}
分配的对象可用于垃圾回收。
表示,内存可能会继续增长,直到达到其分配的限制为止,但此后对象将被垃圾收集。在netbeans之外运行您的代码,并在其上运行jvisualvm。看看到底发生了什么。
答案 5 :(得分:0)
我运行了上面的代码,我可以确认这不是内存泄漏。因为当我运行GC时,所有的ArrayList对象都被回收。假设它注释了应用程序代码并没有累积问题
此致 拉莉莎