JVM向OS发回内存

我有一个关于JVM内存管理的问题(至少对于SUN的内存管理问题)。

我想知道如何控制JVM将未使用的内存发送回OS(在我的情况下为Windows)这一事实。

我写了一个简单的java程序来说明我的期望。 使用-Dcom.sun.management.jmxremote选项运行它,以便您也可以使用jconsole监视堆。

使用以下程序:

package fr.brouillard.jvm; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.LinkedList; import java.util.List; public class MemoryFree { private BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); private List usedMemory = new LinkedList(); private int totalMB = 0; private int gcTimes = 0; public void allocate(int howManyMB) { usedMemory.add(new byte[howManyMB * 1024 * 1024]); totalMB += howManyMB; System.out.println(howManyMB + "MB allocated, total allocated: " + totalMB + "MB"); } public void free() { usedMemory.clear(); } public void gc() { System.gc(); System.out.println("GC " + (++gcTimes) + " times" ); } public void waitAnswer(String msg) { System.out.println("Press [enter]" + ((msg==null)?"":msg)); try { reader.readLine(); } catch (IOException e) { } } public static void main(String[] args) { MemoryFree mf = new MemoryFree(); mf.waitAnswer(" to allocate memory"); mf.allocate(20); mf.allocate(10); mf.allocate(15); mf.waitAnswer(" to free memory"); mf.free(); mf.waitAnswer(" to GC"); mf.gc(); mf.waitAnswer(" to GC"); mf.gc(); mf.waitAnswer(" to GC"); mf.gc(); mf.waitAnswer(" to GC"); mf.gc(); mf.waitAnswer(" to exit the program"); try { mf.reader.close(); } catch (IOException e) {} } } 

第一次GC完成后(预期的内容)内部堆是空闲的,但内存只从第三个GC开始发送回操作系统。 在第四个之后,完整分配的内存被发送回OS。

如何设置JVM来控制此行为? 实际上我的问题是我需要在服务器上运行几个CITRIX客户端会话,但我希望服务器上运行的JVM尽快释放内存(我的应用程序中只有很少的高消耗内存函数)。

如果无法控制此行为,我是否可以像这样使用并增加操作系统虚拟内存,让操作系统按需使用它而不会出现大的性能问题。 例如,在4GB服务器上有10个java进程的1GB内存(堆中只有100MB实际分配的对象),当然会有足够的虚拟内存。

我猜其他人已经遇到过这样的问题/问题。

谢谢你的帮助。

要控制堆返回到OS,从Java 5开始,使用-XX:MaxHeapFreeRatio选项,如调优指南中所述 。

如果您认为您的问题与此问题存在显着差异,请指出如何处理。

首先,System.gc()也可能什么都不做。 你真的不能依赖它来按照你的建议进行垃圾收集。

其次,你需要通过使用来监控GC的实际情况

 -verbosegc -XX:+PrintGCDetails 

在你的java调用中。 或者通过使用JConsole,它听起来像你正在做的。 但那个System.gc()让我害怕你在计算错误的东西……

我怀疑当你说第二次或第三次垃圾收集是释放内存的时候,你只是错误地计算了垃圾收集。 对GC的请求不是GC! 因此,检查PrintGCDetails打印出的日志( 按照这种方式解释 )。

实际上我的问题是我需要在服务器上运行几个CITRIX客户端会话,但我希望服务器上运行的JVM尽快释放内存(我的应用程序中只有很少的高消耗内存函数)。

虽然你的问题是有效的,但你想要的解决方案有点阴暗。 出于这个原因,JVM需要一个堆大小 – 这样可以保证这个空间可以运行。看起来你倾向于启动一个应用程序,然后等待JVM调整其堆的大小,然后启动另一个这样的您正在超额预订机器上的资源。 不要这样做,因为一旦应用程序占用的内存超出了您的预期,它将会爆炸,但它有权获得。

我完全相信你不想以这种方式微观管理Java的堆。

阅读足够的http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html来了解几代人以及更大/更小的堆的权衡。

在你看到可测量的减速之前我不会担心它。 如果进程分配了未使用的内存,则操作系统会根据需要将未使用的块交换到磁盘。