¿GC libera memoria en el sistema operativo?

Cuando el recolector de elementos no utilizados se ejecuta y libera memoria, esta memoria vuelve al sistema operativo o se guarda como parte del proceso. Tenía la fuerte impresión de que la memoria nunca se libera de nuevo al sistema operativo sino que se mantiene como parte del área / grupo de memoria para ser reutilizada por el mismo proceso.

Como resultado, la memoria real de un proceso nunca disminuiría. Un artículo que me recordó fue este y Java’s Runtime está escrito en C / C ++, ¿entonces supongo que se aplica lo mismo?

Actualizar
Mi pregunta es sobre Java. Menciono C / C ++ ya que asumo que la asignación / desasignación de Java es realizada por JRE usando alguna forma de malloc / delete

El HotSpot JVM libera la memoria al sistema operativo, pero lo hace de mala gana ya que cambiar el tamaño del montón es caro y se supone que si necesita ese montón una vez lo necesitará de nuevo.

Puede hacerlo más agresivo configurando -XX:GCTimeRatio=19 -XX:MinHeapFreeRatio=20 -XX:MaxHeapFreeRatio=30 que le permitirá dedicar más tiempo de CPU a la recostackción y limitar la cantidad de memoria de montón asignada pero no utilizada después de un ciclo GC

Suponiendo que está utilizando un recostackdor simultáneo, también puede establecer -XX:InitiatingHeapOccupancyPercent=N con N en un valor bajo para permitir que el GC ejecute colecciones simultáneas casi continuamente, lo que consumirá aún más ciclos de CPU pero reducirá el montón antes. En general, esto no es una buena idea, pero en algunos tipos de máquinas con muchos núcleos de CPU de repuesto pero con poca memoria, puede tener sentido.

Si está utilizando un recostackdor con un objective de tiempo de pausa predeterminado (CMS o G1) también puede relajar ese objective para colocar menos restricciones en el recostackdor, o puede cambiar el colector paralelo para priorizar la huella en los tiempos de pausa.

Además, con Java 9 -XX:-ShrinkHeapInSteps opción -XX:-ShrinkHeapInSteps se puede utilizar para aplicar la contracción causada por las dos opciones anteriores de forma más agresiva. Pedazo relevante de OpenJDK .

Tenga en cuenta que la reducción de la capacidad y el comportamiento depende del recolector de basura elegido. Por ejemplo, G1 solo obtuvo la capacidad de devolver fragmentos no utilizados en el medio del montón con jdk8u20.

Por lo tanto, si es necesario reducir el tamaño del conjunto, debe probarse una versión de JVM y una configuración de GC en particular.

GC Logging con PrintAdaptiveSizePolicy también puede proporcionar información, por ejemplo, cuando la JVM intenta usar más memoria para que la generación joven PrintAdaptiveSizePolicy algunos objectives.

También hay un borrador de JEP para que G1 ceda la memoria con más entusiasmo, pero al ser un borrador, no está claro si se implementará o no. También menciona que Shenandoah y el VM OpenJ9 tienen la capacidad.

La JVM libera la memoria de respaldo en algunas circunstancias, pero (por motivos de rendimiento) esto no sucede siempre que parte de la memoria es basura. También depende de la JVM, el sistema operativo, el recolector de basura, etc. Puede ver el consumo de memoria de su aplicación con JConsole, VisualVM u otro generador de perfiles.

Ver también este informe de error relacionado

Este artículo explica cómo funciona el GC en Java 7. En pocas palabras, hay muchos recolectores de basura disponibles. Por lo general, la memoria se guarda para el proceso de Java y solo algunos GC la lanzan al sistema (a petición, creo). Pero la memoria utilizada por el proceso de Java no crecerá indefinidamente, ya que existe un límite superior definido por la opción Xmx (que normalmente es de 256 m, pero creo que depende del sistema operativo / máquina).