简体   繁体   English

为什么Java System.gc()没有按预期工作?

[英]Why Java System.gc() not working as expected?

I have two functions below one is insert() and other one is startGC(). 我有两个函数,一个是insert(),另一个是startGC()。

I will call insert() method first which will take some 300MB of heap space. 我将首先调用insert()方法,这将占用大约300MB的堆空间。 After that I will call startGC() which should release the memory allocated in heap because all the vector objects are local to the function but its not happening. 之后,我将调用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();
}

My Question: 我的问题:

1) Why Garbage collect is not working in this example. 1)为什么垃圾收集在这个例子中不起作用。

2) How to make JVM to garbage collect all unused memory blocks. 2)如何使JVM垃圾收集所有未使用的内存块。

Any code sample to achieve the same. 任何代码示例都实现相同。

  1. In what way isn't it working? 它以什么方式工作?
  2. You can't tell the JVM to start a Garbage Collection, you can only suggest that you think it is a good idea by invoking System.gc(). 您无法告诉 JVM启动垃圾收集,您只能通过调用System.gc()来建议您认为这是一个好主意。

From the JavaDoc : 来自JavaDoc

Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. 调用gc方法表明Java虚拟机花费了大量精力来回收未使用的对象,以使其当前占用的内存可用于快速重用。 When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects. 当控制从方法调用返回时,Java虚拟机已尽最大努力从所有丢弃的对象中回收空间。

If I try 如果我试试

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());
}

it prints 它打印

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

So it appears to work for me. 所以它似乎对我有用。

是关于Java垃圾收集的一个很好的阅读。

You can't force a collection and it is the wrong approach. 你不能强迫收集,这是错误的方法。 You should read up on the different, garbage-collection parameters that you can pass to your JVM and pick ones that will maximise the performance you are interested in (overall throughput? minimum pauses? etc). 您应该阅读可以传递给JVM的不同垃圾收集参数,并选择能够最大化您感兴趣的性能的参数(总吞吐量?最小暂停?等)。 The code itself should not really worry about gc. 代码本身不应该真的担心gc。

As already said, you can only suggest the GC to delete your objects. 如前所述,您只能建议GC删除您的对象。 The only thing you might do is setting the heapmax (for example: -Xmx512m). 您可能要做的唯一事情是设置heapmax(例如:-Xmx512m)。 You can affect the run of the gc this way. 您可以通过这种方式影响gc的运行。 This is probably one of the biggest disadvantages of Java. 这可能是Java最大的缺点之一。 If you really need the heap, your have to use languages like cpp, which won´t use a vm to compile the application. 如果你真的需要堆,你必须使用像cpp这样的语言,它们不会使用vm来编译应用程序。

The JVM is recycling the memory it has been allocated. JVM正在回收已分配的内存。

It will not necessary give it back to the OS. 它不必将其返回给操作系统。

Please have a look this post Java still uses system memory after deallocation of objects and garbage collection that explains how it works. 请看一下这篇文章, 在解除对象和垃圾收集后, Java仍然使用系统内存来解释它是如何工作的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM