java memory-management jvm

java - JVM devuelve la memoria al sistema operativo



java 8 memory model (3)

Antes que nada, System.gc () tampoco podría hacer nada. Realmente no puedes confiar en que haga una recolección de basura de la manera que estás sugiriendo.

En segundo lugar, querrás monitorear lo que realmente sucede con el GC al usar

-verbosegc -XX:+PrintGCDetails

en tu invocación a java O usando JConsole, que parece que estás haciendo. Pero ese System.gc () me tiene asustado de que estés contando lo incorrecto ...

Sospecho que cuando dices que la segunda o tercera recolección de basura es cuando libera la memoria, estás contando las colecciones de basura. ¡Una solicitud a GC no es un GC! Por lo tanto, compruebe los registros (los interpreta de esta manera ) que PrintGCDetails imprime.

De hecho, mi problema es que necesito ejecutar varias sesiones de clientes CITRIX en un servidor, pero me gustaría que las JVM en ejecución en el servidor liberen la memoria lo antes posible (en mi aplicación solo tengo algunas funciones de memoria de alto consumo).

Si bien tu problema es válido, la solución que estás buscando es un poco turbia. La JVM necesita un tamaño de pila exactamente por esta razón, para que se pueda garantizar que este espacio se ejecute. Parece que te estás inclinando hacia el lanzamiento de una aplicación, luego esperas a que la JVM dimensione su almacenamiento y luego ejecute otra. que está sobrevesando los recursos en la máquina. No hagas eso, porque todo explotará una vez que una aplicación esté tomando más memoria de la que creías que tendría, pero a la que tiene derecho.

Estoy totalmente convencido de que no quieres ser micro administrador del montón de Java de esta manera.

Lea lo suficiente de http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html para comprender las generaciones y cuáles son las compensaciones de un montón más grande / más pequeño.

Tengo una pregunta sobre la gestión de la memoria JVM (al menos para la gestión de la memoria de Sun).

Me gustaría saber cómo controlar el hecho de que la JVM envía de vuelta la memoria no utilizada al sistema operativo (Windows en mi caso).

Escribí un programa simple de Java para ilustrar lo que esperaba. Ejecútelo con la opción -Dcom.sun.management.jmxremote para que también pueda supervisar el montón con jconsole, por ejemplo.

Con el siguiente programa:

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<byte[]> usedMemory = new LinkedList<byte[]>(); 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) {} } }

El montón interno es gratuito una vez que se realiza el primer GC (lo que se espera), pero la memoria solo se envía de vuelta al SO a partir del tercer GC. Después de la cuarta, la memoria asignada completa se envía de vuelta al sistema operativo.

¿Cómo configurar la JVM para controlar este comportamiento? De hecho, mi problema es que necesito ejecutar varias sesiones de clientes CITRIX en un servidor, pero me gustaría que las JVM en ejecución en el servidor liberen la memoria lo antes posible (en mi aplicación solo tengo algunas funciones de memoria de alto consumo).

Si no se puede controlar este comportamiento, ¿puedo dejarlo así y aumentar la memoria virtual del sistema operativo y dejar que el sistema operativo lo use como lo desee sin grandes problemas de rendimiento? Por ejemplo, ¿habría problemas para tener 10 procesos Java de 1 GB de memoria (con solo 100 MB de objetos asignados reales en el montón) en un servidor de 4 GB con suficiente memoria virtual, por supuesto.

Supongo que otras personas ya enfrentaron tales preguntas / problemas.

Gracias por tu ayuda.


No me preocuparía hasta que veas ralentizaciones mensurables. Si un proceso tiene memoria asignada que no está utilizando, el sistema operativo intercambiará los fragmentos no utilizados en el disco según sea necesario.


Para controlar el retorno del montón al sistema operativo, desde Java 5 en adelante, use la opción -XX:MaxHeapFreeRatio , tal como se describe en la guía de ajuste .

Si siente que su pregunta es significativamente diferente de esta , por favor señale cómo.