OOM de desbordamiento de memoria Java mediante análisis Mat

Ejemplo

package com.rumenz;

import java.util.ArrayList;
import java.util.List;

public class OutOfMemory {

    public static void main(String[] args) {
         List<UserTest> res=new ArrayList<>();
         while (true){
             res.add(new UserTest());
         }
    }
}

class UserTest{

}

VM agregar parámetros

-Xms20m -Xmx20m

Salida:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.rumenz.OutOfMemory.main(OutOfMemory.java:11)

Explicación:

El tamaño de la memoria del montón de la JVM controlada por el parámetro VM es de solo 20 m. El programa sigue creando objetos y los objetos asignan memoria en el montón. Siguen agregando objetos a la Lista sin recolección de basura, lo que genera un desbordamiento de la memoria del montón (OutOfMemoryError) .

Montón de análisis de herramientas de tapete

1. Descargue el software de análisis de Mat: https: //www.eclipse.org/mat/d ...

2. Agregue el parámetro de VM: -XX: + HeapDumpOnOutOfMemoryError para abrir el desbordamiento de la memoria del montón y exportar la memoria del montón al archivo, el valor predeterminado está en el directorio raíz del proyecto. Si necesita especificar otras rutas con -XX: HeapDumpPath = / tmp, se generará un nombre similar Archivo java_pid28790.hprof.

3. Utilice Mat para abrir el archivo hprof

OOM de desbordamiento de memoria Java mediante análisis Mat

java.lang.Object [14053] Significado:

La lista es esencialmente una matriz Object [], y 14053 es el número de objetos almacenados en ella.

  • Montón poco profundo significa: el tamaño real del montón ocupado por el objeto (sin incluir el tamaño de otros objetos referenciados)
  • Montón retenido significa: la ocupación real del objeto + el tamaño del objeto referenciado contenido

Método de cálculo de montón superficial

En este caso: el montón superficial ocupa 112448 bytes y el montón retenido ocupa 337296 bytes.

List res = new ArrayList <> (); res es una variable local, la memoria se asigna en la pila, res almacena la dirección de memoria del montón (referencia) del objeto de instancia UserTest y la compresión de puntero está activada en JDK1.8 (-XX: + UseCompressedOops ), en el sistema de 64 bits, la referencia ocupa 4 bytes y el puntero de referencia en el sistema de 64 bits sin compresión de puntero ocupa 8 bytes.

当前案例未打开指针压缩:
14053个引用地址占用内存大小: `14053*8=112424`,`Shallow Heap`占用`112448`字节,还有24字节明显就是res容器本身占用的内存大小.

El montón superficial de la matriz ocupa el cálculo de la memoria:

16 bytes of overhead 对象的头
4 bytes length 存储容器长度
4 bytes padding 字节对其

16 bytes de sobrecarga + 4 bytes de longitud + 4 bytes de relleno = 24 bytes

Método de cálculo de montón retenido

Tamaño de montón retenido = tamaño de montón poco profundo + tamaño real del objeto al que se hace referencia

Se ha calculado el montón superficial

El tamaño real del objeto referenciado: en este caso, dado que UserTest es un objeto vacío, cada objeto de instancia de UserTest solo ocupa 16 bytes de encabezado de objeto. Hay 14053 objetos de instancia en total, por lo que un total de 14053 * 17 = 224848 está ocupado.

Retained Heap=112424+224848=337296和Mat分析的结果一致.

Supongo que te gusta

Origin blog.csdn.net/qwe123147369/article/details/109111987
Recomendado
Clasificación