java.lang.OutOfMemoryError: espacio de almacenamiento dinámico de Java

96

Recibo el siguiente error al ejecutar un programa de subprocesos múltiples

java.lang.OutOfMemoryError: Java heap space

El error anterior ocurrió en uno de los hilos.

  1. Hasta donde yo sé, el espacio de montón está ocupado solo por variables de instancia. Si esto es correcto, entonces por qué se produjo este error después de funcionar bien durante algún tiempo, ya que el espacio, por ejemplo, las variables se asignan en el momento de la creación del objeto.

  2. ¿Hay alguna forma de aumentar el espacio del montón?

  3. ¿Qué cambios debo hacer en mi programa para que ocupe menos espacio en el montón?

Yatendra Goel
fuente

Respuestas:

104

Si desea aumentar su espacio de pila, puede usarlo java -Xms<initial heap size> -Xmx<maximum heap size>en la línea de comando. De forma predeterminada, los valores se basan en la versión de JRE y la configuración del sistema. Puede obtener más información sobre las opciones de VM en el sitio web de Java .

Sin embargo, recomendaría perfilar su aplicación para averiguar por qué se está consumiendo el tamaño de su montón. NetBeans tiene un generador de perfiles muy bueno incluido. Creo que usa jvisualvmdebajo del capó. Con un generador de perfiles, puede intentar encontrar dónde se están creando muchos objetos, cuándo se recolectan los objetos basura y más.

Thomas Owens
fuente
1
Estoy usando Netbeans pero no sé cómo usar Profiler. Me gustaría saber más sobre el generador de perfiles para poder usarlo para encontrar pérdidas de memoria en mi aplicación.
Yatendra Goel
Agregué un enlace a una página en el sitio de NetBeans ( profiler.netbeans.org ) que tiene muy buena documentación sobre el perfil, desde los conceptos básicos hasta el uso más avanzado.
Thomas Owens
Los valores predeterminados cambian con las versiones de Java, sería bueno incluir esta información en su respuesta.
Dariusz
Acabo de solucionar un problema similar y lo intenté primero: java -jar division.jar -Xmx512m -Xms512m - esto me da el mismo error pero cuando lo hago así: java -Xmx512m -Xms512m -jar division.jar - todo está bien. Entonces, el orden de los parámetros también es importante.
hipokito
@hipokito Los argumentos después de que el archivo jar se pasan al método main () del archivo jar como args []
Asu
29

1.- Sí, pero se refiere básicamente a toda la memoria que usa tu programa.

2.- Sí ver opciones Java VM

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size

Es decir

java -Xmx2g asigne 2 gigabytes de RAM como máximo a su aplicación

Pero primero debería ver si no tiene una pérdida de memoria.

3.- Depende del programa. Intente detectar fugas de memoria. Esta pregunta sería muy difícil de responder. Últimamente puedes crear un perfil usando JConsole para tratar de averiguar a dónde va tu memoria

OscarRyz
fuente
mientras que (verdadero);)
Gal Bracha
8

Es posible que desee consultar este sitio para obtener más información sobre la memoria en la JVM: http://developer.streamezzo.com/content/learn/articles/optimization-heap-memory-usage

Me ha resultado útil usar visualgc para observar cómo se llenan las diferentes partes del modelo de memoria, para determinar qué cambiar.

Es difícil determinar qué parte de la memoria se llenó, por lo tanto, visualgc, ya que es posible que desee cambiar la parte que tiene un problema, en lugar de simplemente decir:

¡Multa! Le daré 1G de RAM a la JVM.

Trate de ser más preciso sobre lo que está haciendo, a la larga probablemente encontrará el programa mejor para ello.

Para determinar dónde puede estar la pérdida de memoria, puede usar pruebas unitarias para eso, probando cuál era la memoria antes y después de la prueba, y si hay un cambio demasiado grande, es posible que desee examinarlo, pero debe realice la comprobación mientras la prueba aún se está ejecutando.

James Black
fuente
6

Para aumentar el tamaño del montón, puede usar el argumento -Xmx al iniciar Java; p.ej

-Xmx256M
Adamski
fuente
6

Puede obtener el tamaño de la memoria del montón a través del siguiente programa.

public class GetHeapSize {
    public static void main(String[] args) {
        long heapsize = Runtime.getRuntime().totalMemory();
        System.out.println("heapsize is :: " + heapsize);
    }
} 

luego, en consecuencia, puede aumentar el tamaño del montón también usando: java -Xmx2g http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html

usuario2663609
fuente
6
  1. Hasta donde yo sé, el espacio de montón está ocupado solo por variables de instancia. Si esto es correcto, entonces por qué se produjo este error después de funcionar bien durante algún tiempo, ya que el espacio, por ejemplo, las variables se asignan en el momento de la creación del objeto.

Eso significa que está creando más objetos en su aplicación durante un período de tiempo de forma continua. Los nuevos objetos se almacenarán en la memoria del montón y esa es la razón del crecimiento en la memoria del montón.

Heap no solo contiene variables de instancia. Almacenará todos los tipos de datos no primitivos (Objetos). La vida útil de estos objetos puede ser corta (bloque de método) o larga (hasta que se hace referencia al objeto en su aplicación)

  1. ¿Hay alguna forma de aumentar el espacio del montón?

Si. Eche un vistazo a este artículo de Oracle para obtener más detalles.

Hay dos parámetros para configurar el tamaño del montón:

-Xms : , que establece el tamaño de pila inicial y mínimo

-Xmx : , que establece el tamaño máximo del montón

  1. ¿Qué cambios debo hacer en mi programa para que ocupe menos espacio en el montón?

Depende de su aplicación.

  1. Establezca la memoria de pila máxima según los requisitos de su aplicación

  2. No provoque pérdidas de memoria en su aplicación

  3. Si encuentra fugas de memoria en su aplicación, busque la causa raíz con la ayuda de herramientas de creación de perfiles como MAT , Visual VM , jconsole , etc. Una vez que encuentre la causa raíz, repare las fugas.

Notas importantes del artículo de Oracle

Causa: el mensaje de detalle Espacio de almacenamiento dinámico de Java indica que el objeto no se pudo asignar en el almacenamiento dinámico de Java. Este error no implica necesariamente una pérdida de memoria.

Posibles razones:

  1. Configuración incorrecta (no asigna suficiente memoria)
  2. La aplicación contiene involuntariamente referencias a objetos y esto evita que los objetos se recolecten como basura
  3. Aplicaciones que hacen un uso excesivo de finalizadores. Si una clase tiene un método de finalización, entonces los objetos de ese tipo no tienen su espacio recuperado en el momento de la recolección de basura. Si el subproceso del finalizador no puede mantenerse al día con la cola de finalización, entonces el montón de Java podría llenarse y se lanzaría este tipo de excepción OutOfMemoryError .

En una nota diferente, use mejores algoritmos de recolección de basura ( CMS o G1GC )

Eche un vistazo a esta pregunta para comprender G1GC

Ravindra babu
fuente
5
  1. En la mayoría de los casos, el código no está optimizado. Suelta aquellos objetos que crees que no serán necesarios más. Evite la creación de objetos en su bucle cada vez. Intenta usar cachés. No sé cómo le va a su aplicación. Pero en programación, también se aplica una regla de la vida normal

    Es mejor prevenir que curar. "No crees objetos innecesarios"

DKSRathore
fuente
3
  1. Las variables locales se encuentran en la pila. El espacio de la pila está ocupado por objetos.

  2. Puede utilizar la -Xmxopción.

  3. Básicamente, el espacio de pila se usa cada vez que asigna un nuevo objeto newy se libera algún tiempo después de que ya no se hace referencia al objeto. Así que asegúrese de no guardar referencias a objetos que ya no necesita.

sepp2k
fuente
1

No, creo que estás pensando en el espacio de la pila. El espacio de la pila está ocupado por objetos. La forma de aumentarlo es -Xmx256m, reemplazando el 256 con la cantidad que necesita en la línea de comando.

Yishai
fuente
1

Para evitar esa excepción, si está utilizando JUnit y Spring, intente agregar esto en cada clase de prueba:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
Aliuk
fuente
0

En netbeans, vaya a la barra de herramientas 'Ejecutar', -> 'Establecer configuración del proyecto' -> 'Personalizar' -> 'ejecutar' de su ventana emergente -> 'Opción VM' -> completar '-Xms2048m -Xmx2048m '. Podría resolver el problema del tamaño del montón.

Xiaogang
fuente