3

我有以下两个函数,一个是 insert(),另一个是 startGC()。

我将首先调用 insert() 方法,这将占用大约 300MB 的堆空间。之后我将调用 startGC() ,它应该释放在堆中分配的内存,因为所有向量对象都是函数本地的,但它没有发生。

private void insert()
 {
         Vector v=new Vector();
         Vector v1=new Vector();
         Vector v2=new Vector();
        String str="Hello";

        for (long i = 0L; i < 999999L; i++) {
            v.add(str + i);
            v1.add(str + i);
            v2.add(str + i);
        }
        v=null;
        v1=null;
        v2=null;
 }

private void startGC()
{
    System.gc();
}

我的问题:

1)为什么垃圾收集在这个例子中不起作用。

2)如何让JVM垃圾收集所有未使用的内存块。

任何实现相同的代码示例。

4

6 回答 6

7
  1. 它以什么方式不起作用?
  2. 您不能告诉JVM 启动垃圾收集,您只能通过调用 System.gc()建议您认为这是一个好主意。

JavaDoc

调用 gc 方法表明 Java 虚拟机花费精力回收未使用的对象,以使它们当前占用的内存可用于快速重用。当控制从方法调用返回时,Java 虚拟机已尽最大努力从所有丢弃的对象中回收空间。

于 2012-07-25T14:17:47.530 回答
2

如果我尝试

private static void insert() {
    List<String> v1 = new ArrayList<>(), v2 = new ArrayList<>(), v3 = new ArrayList<>();
    String str = "Hello";

    for (long i = 0L; i <= 999999; i++) {
        v1.add(str + i);
        v2.add(str + i);
        v3.add(str + i);
    }
}

private static void startGC() {
    System.gc();
}

private static long mbUsed() {
    return (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024/1024;
}

public static void main(String... args)  {
    startGC();
    System.out.printf("Memory used before insert %,d MB%n", mbUsed());
    insert();
    System.out.printf("Memory used after insert %,d MB%n", mbUsed());
    startGC();
    System.out.printf("Memory used after GC %,d MB%n", mbUsed());
}

它打印

Memory used before insert 2 MB
Memory used after insert 265 MB
Memory used after GC 5 MB

所以它似乎对我有用。

于 2012-07-25T14:25:30.037 回答
1

是一本关于 Java 垃圾收集的好读物。

于 2012-07-25T14:20:10.343 回答
1

您不能强制收集,这是错误的方法。您应该阅读可以传递给 JVM 的不同的垃圾收集参数,并选择可以最大化您感兴趣的性能的参数(总体吞吐量?最小暂停?等)。代码本身不应该真正担心 gc。

于 2012-07-25T14:25:52.843 回答
1

如前所述,您只能建议 GC 删除您的对象。您唯一可能做的就是设置 heapmax(例如:-Xmx512m)。您可以通过这种方式影响 gc 的运行。这可能是 Java 的最大缺点之一。如果你真的需要堆,你必须使用像 cpp 这样的语言,它不会使用 vm 来编译应用程序。

于 2012-07-25T14:33:35.447 回答
1

JVM 正在回收它已分配的内存。

没有必要将其交还给操作系统。

请看一下这篇文章Java 在释放对象和垃圾收集后仍然使用系统内存,解释了它是如何工作的。

于 2012-07-25T14:40:05.907 回答