El montón Java se usa para almacenar instancias de objetos. Por lo tanto, si creamos continuamente objetos y nos aseguramos de que haya una ruta accesible entre la raíz GC y el objeto creado para evitar que el objeto sea recolectado de basura, entonces, cuando se crean demasiados objetos, causará una memoria de montón insuficiente, lo que aumentará una excepción de MemoryError.
/** * @author xiongyongshun * vm args: java -xms10m -xmx10m -xx:+HeapdumponoutoFmemoryError */public class outOfMemoryErrortest {public static void main (string [] {list <Steger> list = new arraylist <> (); int i = 0; while (true) {list.add (i ++); }}}Lo anterior es un código que plantea una excepción OutOfMemoryError. Podemos ver que evita que el objeto sea recolectado basura creando y guardando constantemente el objeto en la lista. Por lo tanto, cuando hay demasiados objetos, la memoria del montón se desbordará.
A través de Java -xms10m -xmx10m -xx:+HeapDumponoutoFmemoryError, establecemos la memoria Heap en 10 megabytes y usamos el parámetro -xx:+HEAPDUMPONOUTOFMORYError para hacer que la instantánea de la memoria actual imprima la instantánea de memoria actual cuando una excepción de MemoryerRor fuera de la excepción de la excepción posterior.
Después de compilar y ejecutar el código anterior, la siguiente salida será:
>>> java -xms10m -xmx10m -xx:+HeapdumponoutoFMemoryError com.test.outofMemoryErrortest 16-10-02 23: 35java.lang.OUTOFMOMORYError: Java SpacedUpduming Head a Java_Pid1810.hprof ... Hous Dump File Created [CEDIMINE CREIDA CREID [CREIDE CREIDACIÓN 0.125 secs] Excepción en el hilo "principal" java.lang.outofMemoryError: Java Heap Space en java.util.arrays.copyof (arrays.java:3210) en java.util.arrays.copyof (arrays.Java:3181) en java.util.arraylist.grow (arraylist.Java:211) java.util.arrayList.ensureExpliCitCapacity (ArrayList.Java:235) en java.util.arrayList.ensureCapacityInternal (ArrayList.Java:227) en java.util.arraylist.add (arraylist.Java:458) en com.test.OUTOFMEMORYERRORT
Java stackoverflowerror
Sabemos que hay un área de memoria llamada pila de máquinas virtuales en el área de datos de tiempo de ejecución del JVM. La función de esta área es: cada método creará un marco de pila cuando se ejecute, que se utiliza para almacenar información, como tablas variables locales, pilas de operando, salidas de métodos, etc.
Por lo tanto, podemos crear una llamada recursiva infinitamente recursiva. Cuando la profundidad recursiva es demasiado grande, el espacio de la pila se agotará, lo que conducirá a una excepción de StackOverFlowror.
Aquí está el código específico:
/** * @author xiongyongshun * vm args: java -xss64k */public } public static void stackOutofMemoryError (int profundidad) {profundidad ++; stackOutofMemoryError (profundidad); }}Después de compilar y ejecutar el código anterior, se emitirá la siguiente información de excepción:
Excepción en el hilo "principal" java.lang.stackoverflowerror en com.test.outofmemoryerRortest.stackoutofMemoryError (outOfMemoryErrortest.java:27)
Desbordamiento de la memoria en el área del método
Tenga en cuenta que debido a que JDK8 ha eliminado la generación permanente y la reemplazó con Metaspace, en JDK8, ninguno de los siguientes dos ejemplos causará java.lang.ouTOFMemoryError: excepción de espacio de Permgen.
Se desborvan constantes a la piscina durante el tiempo de ejecución
En Java 1.6 y versiones anteriores de Hotspot JVM, existe un concepto de generación permanente, es decir, el mecanismo de recolección de generación de GC se extiende al área del método. En el área del método, se utiliza una parte de la memoria para almacenar piscinas constantes. Por lo tanto, si hay demasiadas constantes en el código, la memoria del grupo constante se agotará, lo que dará como resultado el desbordamiento de la memoria. Entonces, ¿cómo agregar una gran cantidad de constantes a la piscina constante? En este momento, debe confiar en el método String.Intern (). La función del método String.Intern () es: si el valor de esta cadena ya existe en el grupo constante, este método devuelve la referencia a la cadena correspondiente en el grupo constante; De lo contrario, agregue el valor contenido en esta cadena a la piscina constante y devuelva la referencia a este objeto de cadena. En JDK 1.6 y versiones anteriores, el grupo constante se asigna en la generación permanente. Por lo tanto, podemos limitar indirectamente el tamaño del grupo constante estableciendo los parámetros "-xx: Permsize" y "-xx: maxPermerMsize".
Tenga en cuenta que la distribución de memoria del método String.Intern () mencionado anteriormente y el grupo constante es solo para JDK 1.6 y versiones anteriores. En JDK 1.7 o superior, el diseño de la memoria es ligeramente diferente porque se elimina el concepto de generación permanente.
El siguiente es un ejemplo de código para implementar el desbordamiento de la memoria de los grupos constantes:
/** * @author xiongyongshun * vm args: -xx: permSize = 10m -xx: maxPermsize = 10m */public runtimeMeconstantPooloomTest {public static void main (string [] args) {list> list = new ArrayList <String> (); int i = 0; while (true) {list.add (string.ValueOf (i ++). Intern ()); }}}Vemos que en este ejemplo, se usa con precisión el método String.Intern () para agregar una gran cantidad de constantes de cadena a la piscina constante, lo que conduce al desbordamiento de la memoria del grupo constante.
Compilamos y ejecutamos el código anterior a través de JDK1.6, y la siguiente salida será:
Excepción en el hilo "Main" java.lang.OutofMemoryError: Permgen Space en java.lang.string.intern (método nativo) en com.test.runtimeconstantpooloomTest.main (runtimeNstantPooloomTest.Java:16)
Cabe señalar que si el código anterior se compila y se ejecuta a través de JDK1.8, habrá la siguiente advertencia y no se generará ninguna excepción:
>>> java -xx: permSize = 10m -xx: maxPermsize = 10m com.test.RuntimeconstantPooloomTest 16-10-03 0: 23Java Hotspot (TM) Advertencia de VM de 64 bits: ignorando opción PermSize = 10m; El soporte se eliminó en 8.0 Java Hotspot (TM) Advertencia de VM del servidor de 64 bits: ignorando la opción maxPermsize = 10m; el apoyo se eliminó en 8.0
Desbordamiento de la memoria en el área del método
La función del área del método es almacenar la información relevante de la clase, como nombres de clase, modificadores de acceso a clase, descripciones de campo, descripciones de métodos, etc. Por lo tanto, si el área del método es demasiado pequeña y se cargan demasiadas clases, el desbordamiento de la memoria del área del método.
// vm args: -xx: permSize = 10m -xx: maxPermsize = 10mPublic de la clase MethodAreaooooMtest {public static void main (string [] args) {while (true) {mejor mejor potencador = new mejor (); potencador.setsuperClass (MethodAreaooomTest.Class); potencador.setUsecache (falso); FORKANCER.SetCallback (nuevo MethodInterceptor () {Public Object Intercept (Object O, Method Method, Object [] Objects, MethodProxy MethodProxy) lanza {return MethodProxy.Invokesuper (o, objetos);}}); potencador.create (); }}}En el código anterior, usamos CGLIB para generar dinámicamente una gran cantidad de clases. En JDK6, ejecutar el código anterior generará un OutOfMemoryError: Excepción del espacio de Permgen:
/System/library/frameworks/javavm.framework/versions/1.6/home/bin/java -jar -xx: permSize = 10m -xx: maxPermsize = 10m Target/test-1.0-snapshot.jar
El resultado de salida es el siguiente:
Causado por: java.lang.OutofMemoryError: Espacio de Permgen en java.lang.classloader.defineclass1 (método nativo) en java.lang.classloader.defineclasscond (classloader.Java:637) en java.lang.classascar.defineclass (classLoader.Java:621)
Desbordamiento de la memoria de Metaspace
En la sección de desbordamiento de memoria del desbordamiento de memoria en el área del método, mencionamos que JDK8 no tiene un concepto de generación permanente, por lo que esos dos ejemplos no lograron el efecto esperado con JDK8. Entonces, en JDK8, ¿hay algún error como el desbordamiento de la memoria en el área del método? Por supuesto, algunos. En JDK8, el área de MetaSpace se utiliza para almacenar información relacionada con la clase, por lo que cuando Metaspace es insuficiente, se lanzará un java.lang.outOfMemoryError: la excepción de MetaSpace.
Tomemos el ejemplo mencionado anteriormente como un ejemplo:
// vm args: -xx: maxTetApacesize = 10mpublic MethodAleAoAmTest {public static void main (String [] args) {while (true) {mejor mejor mejor = new mejor (); potencador.setsuperClass (MethodAreaooomTest.Class); potencador.setUsecache (falso); FORKANCER.SetCallback (nuevo MethodInterceptor () {Public Object Intercept (Object O, Method Method, Object [] Objects, MethodProxy MethodProxy) lanza {return MethodProxy.Invokesuper (o, objetos);}}); potencador.create (); }}}La parte del código de este ejemplo no se ha cambiado. La única diferencia es que necesitamos usar JDK8 para ejecutar este código y establecer el parámetro -xx: maxTetAspacesize = 10m. Este parámetro le dice a JVM que el tamaño máximo de Metaspace es de 10 m.
Luego usamos JDK8 para compilar y ejecutar este ejemplo, y generamos la siguiente excepción:
>>> java -jar -xx: maxTetApacesize = 10m Target/test -1.0 -snapshot.Jarexception en hilo "principal" java.lang.outofmemoryError: metaspace en net.sf.cglib.core.abstractclassGenerator.generate (abstractClassGenerator.Java:345) ATT net.sf.cglib.proxy.enhancer.generate (potencer.java:492) en net.sf.cglib.core.abstractclassgenerator $ classLoaderData.get (abstractClassGenerator.Java:114) en net.sf.cglib.core.abstractclassgenerator.craate (abstractclassgenerater en net.sf.cglib.proxy.enhancer.createhelper (potencer.java:480) en net.sf.cglib.proxy.enhancer.create (potencer.java:305) en com.test.methodareaoomTest.Main (Metheteaomtest.java:22)
Resumir
Lo anterior se trata de excepciones de desbordamiento de memoria común y ejemplos de código en este artículo, espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a otros temas relacionados en este sitio. Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!