Buen artículo en profundidad de JVM, recopilador CMS y análisis de registros de GC y explicación detallada del problema de posicionamiento

Inserte la descripción de la imagen aquí
Combate de coleccionistas de CMS

Las últimas preguntas de entrevistas reales para empresas de Internet de primera línea recopiladas en 2020 (todas organizadas en documentos), hay muchos productos secos, incluidas explicaciones detalladas de netty, primavera, hilo, nube de primavera, etc., también hay planes de aprendizaje detallados, preguntas de entrevista, etc. Siento que estoy en la entrevista Esta sección es muy clara: para obtener la información de la entrevista, simplemente: haga clic aquí para obtenerla !!! Contraseña: CSDNInserte la descripción de la imagen aquí

Comienza el combate real, ¿estás listo?

Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Código de escenario empresarial simulado:

@RestController
public class IndexController {
    
    
/***
 * 存 big 对象
 * @return
 */
@GetMapping("/put")
public String process() {
    
    
   ArrayList<User> users = queryUsers();
   for (User user:users){
    
    
      //TODO 业务操作
   }
   return "ok";
}
private ArrayList<User> queryUsers() {
    
    
   ArrayList<User> users = new ArrayList<>();
   for (int i = 0; i < 50000; i++) {
    
    
      users.add(new User(i, "java2b"));
   }
   return users;
}
}
public class User {
    
    

   private int id;
   private String name;
   private byte[] data;

   public User(int id, String name) {
    
    
      this.id = id;
      this.name = name;
      data=new byte[1 * 128 * 1024];
   }
}

Información del colector de salida:

/***
 * 打印 jvm 信息
 * @return
 */
@GetMapping("/info")
public String info() {
    
    
   List<GarbageCollectorMXBean> garbages = ManagementFactory.getGarbageCollectorMXBeans();
   StringBuilder stringBuilder = new StringBuilder();
   for (GarbageCollectorMXBean garbage : garbages) {
    
    
      stringBuilder.append("垃圾收集器:名称=" + garbage.getName() + ",收集=" + garbage.getCollectionCount() + ",总花费时间="
              + garbage.getCollectionTime());
      // + ",内存区名称=" + Arrays.deepToString(garbage.getMemoryPoolNames()));
      stringBuilder.append("\r\n");
   }
   MemoryMXBean memory = ManagementFactory.getMemoryMXBean();
   MemoryUsage headMemory = memory.getHeapMemoryUsage();
   long MB = 1024 * 1024;
   stringBuilder.append("head 堆:");
   stringBuilder.append("\t 初始(M):" + headMemory.getInit() / MB);
   stringBuilder.append("\t 最大(上限)(M):" + headMemory.getMax() / MB);
   stringBuilder.append("\t 当前(已使用)(M):" + headMemory.getUsed() / MB);
   stringBuilder.append("\t 提交的内存(已申请)(M):" + headMemory.getCommitted() / MB);
   stringBuilder.append("\t 使用率:" + headMemory.getUsed() * 100 / headMemory.getCommitted() + "%");
   return stringBuilder.toString();
}

Generando un paquete jar implementado en los
parámetros de inicio del servidor :

 java -Xms256m -Xmx256m -verbose:gc -Xloggc:/root/jvm/gc-cms.log -XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintHeapAtGC -XX:HeapDumpPath=/root/jvm/dump.hprof -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCTimeStamps -XX:+PrintCommandLineFlags -XX:+PrintFlagsFinal -XX:+PrintGCDetails -XX:+UseCMSCompactAtFullCollection -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=6666 -Djava.rmi.server.hostname=192.168.0.31 -jar /root/jvm/jvm-web-0.0.1-SNAPSHOT.jar > catalina.out &

Aquí necesitamos insertar el significado de los parámetros de JVM.

Parámetros detallados de JVM:

Significado del parámetro JVM

-XX: -CMSPrecleaningEnabled
no realiza una limpieza previa. Aquellos que han pasado nuestros artículos anteriores saben que CMS tendrá un trabajo de limpieza previa durante el período de marcado y remarcado simultáneos, y esta pasada se intentará en 5 segundos. Espera a que llegue YGC. Para no perder mucho tiempo en la fase de re-marcado posterior para marcar la nueva generación de objetos.

-XX: + UseConcMarkSweepGC
Este parámetro iniciará el recopilador de CMS. La nueva generación predeterminada es ParNew, también puede configurar Serial como el colector de nueva generación. Este parámetro es equivalente a -Xconcgc.

-XX: ParallelGCThreads
es un procesador paralelo, por supuesto, también puede especificar el número de subprocesos. El número predeterminado de subprocesos simultáneos es: (ParallelGCThreads + 3) / 4).
-XX: ConcGCThreads
o -XX: ParallelCMSThreads; Además de la forma de configurar los subprocesos anterior, también puede configurar manualmente el número de subprocesos CMS concurrentes mediante cualquiera de estos dos parámetros

-XX: CMSInitiatingOccupancyFraction
Debido a que el recolector de CMS no es exclusivo, la aplicación aún funciona durante la recolección de basura, por lo que debe dejar suficiente memoria para la aplicación; de lo contrario, activará FGC. ¿Y cuándo funciona CMS GC? Se puede configurar mediante este parámetro, que representa el porcentaje de uso de memoria de la generación anterior. Cuando se alcanza este umbral, se ejecutará CMS. El valor predeterminado es 68. Si la memoria de la generación anterior crece rápidamente, se recomienda reducir el umbral para evitar FGC. Si el crecimiento es lento, puede aumentar el umbral para reducir el número de CMS GC. Mejore el rendimiento.

-XX: + UseCMSCompactAtFullCollection
Debido a que CMS usa un algoritmo de limpieza de marcas, no se puede evitar la fragmentación de la memoria. Este parámetro especifica una desfragmentación después de cada CMS.

-XX: CMSFullGCsBeforeCompaction Dado que cada desfragmentación afectará al rendimiento, puede usar este parámetro para establecer cuántas veces se desfragmentará CMS, que es la compresión de memoria.

-XX: + CMSClassUnloadingEnabled
permite el reciclaje de metadatos de clases.

-XX: CMSInitiatingPermOccupancyFraction

Cuando la tasa de ocupación del área permanente alcance este porcentaje, inicie el reciclaje de CMS (siempre que -XX: + CMSClassUnloadingEnabled esté activado).

-XX: UseCMSInitiatingOccupancyOnly

Indica que la recuperación de CMS solo se realiza cuando se alcanza el umbral.

XX: CMSWaitDuration = 2000
Debido a que la condición CMS GC es relativamente simple, la JVM tiene un subproceso para escanear el área Antigua con regularidad. El intervalo de tiempo se puede especificar mediante este parámetro (en milisegundos) y el valor predeterminado es 2s.
Parámetros de la herramienta JVM:
significado del parámetro JVM


-XX: + PrintGCDateStamps Imprime la marca de tiempo del registro del GC
-XX: + PrintGCDetails Imprime los detalles del GC
-XX: + PrintGCTimeStamps Imprime el tiempo que tarda la recolección de basura en comenzar a ejecutarse
-Xloggc: Salida de información de recolección de basura al archivo especificado
-verbose: gc Print GC log
-XX: + PrintGCApplicationStopedTime Ver el tiempo de suspensión de la aplicación causado por gc
XX: + PrintTenuringDistribution log de promoción de objetos
-XX: + HeapDumpOnOutOfMemoryError Archivo de volcado de salida cuando la memoria se desborda

Inserte la descripción de la imagen aquí

Efecto de inicio:Inserte la descripción de la imagen aquí

acceso:Inserte la descripción de la imagen aquí

Request put: Veamos el efecto después de acceder al método put a través de http:Inserte la descripción de la imagen aquí

Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Durante la operación, encontramos que una gran cantidad de objetos entraron en la vejez, activaron el gc completo y cms se ha ido acumulando.

La tasa de utilización alcanzó el 99%, y cms no se detuvo ni un momento:Inserte la descripción de la imagen aquí

Análisis de registrosInserte la descripción de la imagen aquí

Versión de análisis de registro 1.0: extraemos un registro para analizar

[GC (Error de asignación) 0K-> 63K (64K), 0.0047147 segundos] 10258K-> 6780K (46144K), [Metaspace: 3434K-> 3434K (1056768K)], 0.0047613 segundos] [Tiempos: usuario = 0.02 sys = 0.00, real = 0.00 segundos] El registro tiene cuatro partes:

GC completo:

Indica que se ha realizado una recolección de basura. No hay una modificación completa al frente, lo que indica que se trata de un GC menor. Tenga en cuenta que no significa que solo la nueva generación es GC, y el STW existente será STW, ya sea la nueva generación o la generación anterior.

Error de asignación:

Muestra que la causa de GC esta vez es porque no hay suficiente espacio en la generación joven para almacenar nuevos datos.

10258K-> 6780K (46144K), la unidad es KB

Los tres parámetros son: la capacidad utilizada del área de memoria (en este caso, la generación joven) antes de GC, la capacidad utilizada del área de memoria después de GC y la capacidad total del área de memoria.

0.0047613 segundos:

Tiempo de GC empleado en esta área de memoria, en segundos

[Tiempos: usuario = 0.04 sys = 0.00, real = 0.01 segundos] :

Representar respectivamente el modo de usuario que consume mucho tiempo, el modo de kernel consume mucho tiempo y el tiempo total Inserte la descripción de la imagen aquí

Versión de Log Analysis 2.0:

Utilizando gceasy en línea para el análisis, abrimos el sitio web y cargamos los registros de gc que producimos, como se muestra en la figura: Inserte la descripción de la imagen aquí

Problemas de optimización: se enumeran 4 problemas que se pueden optimizar para el uso de memoria de metaespacio de nueva generación y generación anterior Inserte la descripción de la imagen aquí

Estadísticas de rendimiento: 97,39%
Inserte la descripción de la imagen aquí
de los cambios de memoria de cada generación
Inserte la descripción de la imagen aquí

El tiempo que consume el recolector de basura CMS en diferentes períodos

Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Clasificación y tiempo de aparición de GC
Inserte la descripción de la imagen aquí

Problema de posicionamiento

Usamos los archivos de instantáneas producidos para localizar el problema: Inserte la descripción de la imagen aquí
JProfiler:

Descargado a la vista abierta local a través de JProfiler Inserte la descripción de la imagen aquí
View, los objetos grandes Inserte la descripción de la imagen aquí
encontramos que la colección ArrayList ocupa el 96% de la memoria, luego echamos un vistazo al fragmento de código que hace un uso intensivo de nuestra colección ArrayList Inserte la descripción de la imagen aquí
para encontrar los códigos correspondientes Inserte la descripción de la imagen aquí
por el código que encontramos método put Desbordamiento de memoria OOM causado por el uso extensivo de la colección ArrayList

para resumir

Creo que todo el mundo entiende el combate real anterior. El proceso general es:

1. Suficiente para simular el escenario real de usuarios de alto volumen del proyecto SpringBoot

2. Configure los parámetros de JVM y luego implemente los datos de supervisión en ejecución para generar archivos de registro.

3. Confirme el problema analizando el archivo de registro.
Los amigos que necesitan el código y el software anteriores, también tienen planes de estudio detallados, preguntas de la entrevista, etc. Siento que la entrevista es muy clara: para obtener solo la información de la entrevista: haga clic aquí para obtenerla !!! Contraseña: CSDN todos pueden hacerlo usted mismo Profundice la impresión en funcionamiento real.Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/a3961401/article/details/109407949
Recomendado
Clasificación