¿Alguien puede explicarme por qué las JVM (no verifiqué demasiadas, pero nunca he visto una que no lo haya hecho de esa manera) necesitan ejecutarse en un tamaño de almacenamiento dinámico fijo? Sé que es más fácil de implementar en un montón contiguo simple, pero Sun JVM ahora tiene más de una década, por lo que esperaría que hayan tenido tiempo para mejorar esto.
La necesidad de definir el tamaño máximo de memoria de su programa en el momento del inicio parece una cosa de los años 60, y luego están las malas interacciones con la gestión de memoria virtual del sistema operativo (GC recuperando datos intercambiados, incapacidad para determinar cuánta memoria es el proceso de Java Realmente usando desde el lado del sistema operativo, se desperdician grandes cantidades de espacio de VM (lo sé, no te importan tus elegantes máquinas de 48 bits ...)). También supongo que los diversos intentos tristes de construir pequeños sistemas operativos dentro de la JVM (servidores de aplicaciones EE, OSGi) son al menos parcialmente responsables de esta circunstancia, porque ejecutar múltiples procesos Java en un sistema invariablemente conduce a recursos desperdiciados porque tiene que dar a cada uno de ellos la memoria que podría tener que usar en el pico.
Sorprendentemente, Google no generó las tormentas de indignación sobre esto que yo esperaría, pero pueden haber sido enterrados bajo los millones de personas que se enteraron del tamaño fijo del montón y simplemente lo aceptaron de hecho.
Respuestas:
Está usted equivocado. El tamaño de almacenamiento dinámico de las JVM no es fijo, solo está limitado:
Establecer un límite superior es necesario por varias razones. Primero, le dice al recolector de basura cuándo entrar en acción. En segundo lugar, evita que la JVM obstruya toda la máquina al consumir demasiada memoria. El tamaño mínimo de almacenamiento dinámico probablemente sea útil para reservar la cantidad de memoria que el programa necesita al menos, para evitar que se quede sin memoria (porque otros procesos consumen demasiado).
fuente
Me imagino que la respuesta tiene algo que ver con la herencia de Java. Originalmente fue diseñado como un lenguaje para ser utilizado para sistemas integrados, donde obviamente los recursos están limitados y no desea que los procesos simplemente engullen lo que esté disponible. También ayuda con la administración del sistema, ya que facilita el aprovisionamiento de recursos en un servidor si puede establecer límites de recursos. Veo que las últimas JVM parecen usar múltiples montones no continuos, aunque, por supuesto, todo aparece como un montón único en su código.
(FWIW, tenía que especificar los requisitos de memoria de un programa en las versiones de Apple anteriores a Darwin MacOS [hasta System 7 de todos modos, que fue la última que usé], que estaba bien entrado en los años 80).
fuente
Debe darle al GC algún mecanismo para decirle cuándo ejecutarse, o su programa ocupará todo el espacio de memoria virtual. Hay muchas formas alternativas de desencadenar GC: tiempo transcurrido, número de asignaciones, número de asignaciones, probablemente otras que no puedo pensar en este momento. En mi opinión, ninguno de esos es tan bueno como simplemente establecer un límite de memoria y ejecutar GC cuando el espacio asignado alcanza ese límite.
La clave es establecer los límites correctos . Miro
-ms
como "esta es la cantidad de memoria que necesita mi aplicación" y-mx
como "nunca debe exceder esta cantidad". En una implementación de producción, los dos deben estar cerca, si no son iguales, y deben basarse en requisitos reales medidos.Sus preocupaciones sobre la memoria virtual "desperdiciada" están fuera de lugar: es virtual, es (casi) gratis. Sí, asignar una asignación demasiado grande al montón significa que no puede iniciar tantos subprocesos ni cargar tantos archivos asignados en memoria. Pero eso es parte del diseño de la aplicación: tiene recursos escasos, necesita particionarlos de manera que permita que su aplicación se ejecute. En un montón de "estilo C", que se expandirá hasta llegar a la parte superior de la memoria, el problema básico es el mismo, simplemente no tiene que pensarlo hasta que esté en problemas.
Lo único que un gran montón podría "desperdiciar" es el espacio de intercambio, porque todos los segmentos de escritura requieren un compromiso del intercambio. Pero eso es parte del diseño del sistema: si desea que se ejecuten muchas JVM en el mismo cuadro, aumente su intercambio o disminuya su asignación de almacenamiento dinámico. Si comienzan a sacudirse, entonces estás tratando de hacer demasiado con el sistema; compre más memoria (y si todavía está ejecutando un procesador de 32 bits, compre una nueva caja).
fuente
Como dice user281377, solo especifica un límite superior de la cantidad de memoria que puede consumir su proceso . Por supuesto, la aplicación en sí solo tomará el espacio que necesita.
Si debe existir un límite superior predeterminado o no, es otra cuestión, tanto a favor como en contra.
fuente