我正在玩一个基本上是树的可怕数据结构,每个节点都在HashMap
个对象中存储对其子节点的引用。每当我需要通过将后一个子树设置为新根时,除了一个除掉根和所有子树之外,我就会遇到麻烦。我认为这可能是我的数据结构中的一些错误,也许是我忘了在那里的一些参考,所以什么都没有资格进行垃圾收集。但我想先尝试一些更简单的方法,并实施以下测试:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class MyNode {
MyNode next;
int somedata;
public MyNode(MyNode n) {
next = n;
somedata = 0;
}
public static void main(String[] args) throws IOException {
MyNode p = new MyNode(null);
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (int i=0; i<10000000; i++) {
MyNode n = new MyNode(p);
p = n;
}
while (p!=null) {
MyNode p1 = p.next;
p.next = null;
p = p1;
}
in.readLine();
}
}
当main到达in.readline()
时,我可以在htop中看到该进程仍然为自己分配了250MB左右,并且没有任何内容被释放。我显然是第一次尝试简单地做
p = null;
而不是while循环。但它没有用,所以我想出了以前的代码。
答案 0 :(得分:1)
您的问题有点不清楚 - 您实际上是在获取OutOfMemoryErrors吗?你想解决什么?您可以通过几个原因看到测试用例中出现的行为:
当GC根目录无法访问垃圾时,不会收集垃圾 - 它只是有资格进行垃圾回收。 GC通常仅在分配失败时触发。由于您实际上并没有在循环中分配任何内存以使引用无效,因此GC完全可能尚未运行。
即使收集垃圾,堆中的内存通常也不会返回给操作系统 - 因此从操作系统的角度来看它不会产生准确的答案。使用VisualVM或者像jmap和jhat这样的工具将是找出实际上仍然在堆上的内容的最佳方法。
答案 1 :(得分:0)
垃圾收集器的行为很复杂,不同的垃圾收集器可以使用根本不同的方法。即使您明确表示,也不能指望垃圾立即被回收 调用它。
答案 2 :(得分:0)
我之前见过这个。
htop不是衡量JVM内存利用率的最佳方法。它一直显示出高分。 VM也喜欢将其堆分配得尽可能高。
我建议使用visualgc或jconsole跟踪JVM附带的jps和jpstat。 http://java.sun.com/performance/jvmstat/#Tools
此外,你有一个可以快速创建大量对象的循环,因此gc现在可能有时间进入。 System.gc不保证实际执行。这是一个暗示,但它通常有效。
另请参阅有关Java堆利用率的帖子: http://it.toolbox.com/blogs/lim/how-to-get-details-on-jvms-heap-utilization-10609
答案 3 :(得分:-4)
您可以使用代码
在10000次循环中手动调用一次垃圾回收System.gc();
然而,有一些副作用,例如垃圾收集器使用额外的cpu时间。