La especificación de la máquina virtual Java estipula que la memoria JVM se divide en varios bloques, como el montón, la pila, el contador de programas, el área de método, etc. En la implementación de JVM del punto de acceso, la memoria de montón se divide en tres partes, la nueva generación, la vejez y la banda persistente. La banda persistente implementa el área de método especificado en la especificación, y diferentes partes del modelo de memoria tendrán errores correspondientes de MemoryError. Luego, discutamos por separado. Creo que la mayoría de los desarrolladores han encontrado este error, y las razones de este error son causadas principalmente por las siguientes razones:
La memoria JVM es demasiado pequeña y el programa no es apretado, lo que resulta en demasiada basura.
Existen varias causas comunes de excepciones OutOfMemoryError:
Solicitudes de error comunes para este error:
Stackoverflowror
Stack Overflow lanza un error java.lang.stackoverflowror. Esto ocurre porque la profundidad de la pila excede la profundidad máxima permitida por la máquina virtual cuando el método se está ejecutando. Esta situación generalmente ocurre debido a los errores del programa. Por ejemplo, escribir una recursión muerta puede causar esta situación. Simulemos el desbordamiento de la memoria en esta situación a través de un código.
import java.util.*; import java.lang.*; clase pública oomTest {public void stackoverflowmethod () {stackoverflowmethod (); } public static void main (string ... args) {oomTest oom = new oomTest (); oom.stackoverflowmethod (); }} Ejecutar el código anterior lanzará la siguiente excepción:
Excepción en el hilo "principal" java.lang.stackoverflowerror en oomtest.stackoverflowmethod (oomtest.java:6)
Desbordamiento del montón (OutOfMemoryError: Java Heap Space)
Cuando la memoria del montón se desborda, la máquina virtual arroja java.lang.OUTOFMemoryError: Java Heap Space. Cuando esto sucede, debemos analizarlo específicamente en función del archivo de volcado generado cuando la memoria se desborda (-xx: +HeapDumpOutoFMemoryErrorJVM Parámetro de inicio del parámetro). Cuando se produce tal problema, puede ser una fuga de memoria o un desbordamiento de memoria.
Si la memoria se filtra, debemos averiguar cómo el objeto filtrado es referencia por la raíz GC y luego analizar la causa de la fuga a través de la cadena de referencia.
Si hay un problema de desbordamiento de memoria, a menudo se debe a que el programa necesita más memoria que la memoria que configuramos para la máquina virtual. En este caso, podemos usar -xmx para resolver este problema.
A continuación demostramos el desbordamiento de esta situación a través del siguiente código:
import java.util.*; import java.lang.*; public class oomTest {public static void main (string ... args) {list <byte []> buffer = new ArrayList <byte []> (); buffer.add (nuevo byte [10*1024*1024]); }} Ejecutamos el código anterior a través del siguiente comando:
java -verbose: gc -xmn10m -xms20m -xmx20m -xx:+printgc oomtest
El programa ingresa a la siguiente información:
[GC 1180K->366K(19456K), 0.0037311 secs] [Full GC 366K->330K(19456K), 0.0098740 secs] [Full GC 330K->292K(19456K), 0.0090244 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at Oomtest.main (oomtest.java:7)
A partir de los resultados de la ejecución, podemos ver que el JVM realizó GC menor una vez y dos veces GC mayor. A partir de la salida de GC mayor, se puede ver que la tasa de uso del área anterior después de GC es de 134k, y la matriz de bytes es de 10 m, lo que se suma a ser mayor que el espacio de la generación anterior, por lo que se lanza una excepción. Si se ajustan -xms21m y -xmx21m, entonces la operación GC no se activará y no habrá excepción.
A través del experimento anterior, se ha verificado una conclusión desde el lado: cuando el objeto es más grande que la memoria restante de la nueva generación, se colocará directamente en la vejez. Cuando la memoria restante de la vejez aún no puede ser descartada, se activará la recolección de basura. Si aún no se puede colocar después de la recolección, se lanzará una excepción de desbordamiento de memoria.
Espacio de Permgen
Sabemos que HotSpot JVM implementa el área de método en la especificación de la máquina virtual Java a través de bandas persistentes, y la piscina constante de tiempo de ejecución se almacena en el área del método. Por lo tanto, el desbordamiento de la banda persistente puede ser el desbordamiento de la piscina constante de tiempo de ejecución, o los objetos de clase guardados en el área del método no se reciclan en el tiempo o la memoria ocupada por la información de clase excede nuestra configuración. Cuando la banda de persistencia se desborda, se lanza Java.lang.OutOfMemoryError: el espacio de Permgen.
Puedo experimentar este problema en los siguientes escenarios cuando trabajo.
Al usar la implementación en caliente de algunos servidores de aplicaciones, nos encontraremos con la implementación en caliente varias veces y encontraremos que la memoria se desborda. Esto se debe a que después de cada implementación en caliente, la clase original no se ha desinstalado.
Si la aplicación en sí es más grande e involucra más bibliotecas de clases, este problema también puede ocurrir cuando la memoria que asignamos a la banda persistente (establecida por -xx: permSize y -xx: maxPermsize) es relativamente pequeña.
Algunos marcos de terceros, como Spring y Hibernate, implementan algunas funciones mejoradas a través de la tecnología de generación de bytecode (como CGLIB), que puede requerir un área de método más grande para almacenar archivos de clase generados dinámicamente.
Sabemos que las constantes de cadena en Java se colocan en una piscina constante. Cuando se ejecuta el método String.Intern (), verificará si los objetos iguales a esta cadena se almacenan en el grupo constante. Si existe, devuelva directamente una referencia al objeto en el grupo constante. Si no existe, agregue esta cadena al grupo constante primero y luego devuelva la referencia a la cadena. Luego podemos simular el desbordamiento del área constante durante el tiempo de ejecución a través del método String.Intern. Simulemos esta situación a través del siguiente código:
import java.util.*; import java.lang.*; public class oomTest {public static void main (string ... args) {list <string> list = new ArrayList <String> (); while (true) {list.Add (uuid.randomuuid (). toString (). Intern ()); }}}Ejecutamos el código anterior a través del siguiente comando:
java -verbose: gc -xmn5m -xms10m -xmx10m -xx: maxPermsize = 1m -xx:+printgc oomtest
La entrada después de ejecutar se muestra en la figura a continuación:
Excepción en el hilo "Main" java.lang.outofMemoryError: espacio de Permgen en java.lang.string.intern (método nativo) en oomtest.main (oomtest.java:8)
A través del código anterior, simulamos con éxito el desbordamiento constante del grupo durante el tiempo de ejecución. Desde el espacio de Permgen en la salida, podemos ver que la banda persistente está desbordando, lo que también verifica la afirmación de que el punto de acceso JVM implementa el área del método a través de la banda persistente como se mencionó anteriormente.
OutOfMemoryError: No se puede crear un hilo nativo
Finalmente, echemos un vistazo al error java.lang.outOfMemoryError: No pueda crear el hilo Natvie. Cuando esto sucede, generalmente es causado por las siguientes dos situaciones:
El número de hilos creados por el programa excede el límite del sistema operativo. Para los sistemas Linux, podemos ver esta limitación a través de Ulimit -u.
La memoria asignada a la máquina virtual es demasiado grande, lo que resulta en muy poca memoria nativa requerida al crear subprocesos. Todos sabemos que el sistema operativo tiene un límite en la memoria de cada proceso. Al comenzar JVM, es equivalente a comenzar un proceso. Si uno de nuestros procesos ocupa 4G de memoria, entonces la memoria restante calculada a través de la siguiente fórmula es la memoria que se puede usar al construir una pila de subprocesos. Total de memoria disponible para la pila de subprocesos = 4g- (valor de -xmx)-(-xx: valor de maxPermsize)-La memoria ocupada por el contador del programa se muestra mediante la fórmula anterior que cuanto más grandes son los valores de -xmx y maxPerMsize, menor es el espacio disponible para la pila de hilos. Cuando la capacidad de pila configurada por el parámetro -xss permanece sin cambios, cuanto menor sea el número de subprocesos que se pueden crear. Por lo tanto, si es imposible crear un hilo nativo debido a esta situación, entonces aumentamos la memoria total ocupada por el proceso o reducimos -xmx o -xss para lograr el propósito de crear más hilos.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.