Etapa 10: Resumen del tema (Capítulo 3: Máquina Virtual)

Capítulo 3: Máquina virtual

1.Estructura de memoria JVM

Requerir

  • División de la estructura de memoria Master JVM
  • En particular, necesita conocer la relación entre el área del método, la generación permanente y el metaespacio.

Comprender la partición de la memoria basada en la ejecución de un fragmento de código Java
Insertar descripción de la imagen aquí

  • Ejecute el comando javac para compilarcódigo fuenteparacódigo de bytes
  • Ejecutar comando java
    1. Crear JVM (Máquina virtual de Java),transferirSubsistema de carga de clasesclase de carga (archivo de código de bytes), almacena la información original de la clase (nombre de la clase, relación de herencia, variables miembro, nombres de otras clases a las que se hace referencia, códigos de método de la clase)área del método(Leer archivos de código de bytes del disco a la memoria)
    2. crearHilo principal, el área de memoria utilizada esPila de máquinas virtuales JVM, comience a ejecutar el método principal
    3. Si se encuentra una clase invisible, el proceso de carga de clases continuará activándose y también se almacenará en el área de métodos .
    4. Para los objetos que deben ser creados por la nueva acción, usemontónmemoria para almacenar
    5. Los objetos que ya no se utilicen serán sustituidos porRecolector de basura(GC) recupera su memoria cuando tiene poca memoria
    6. Al llamar a un método, elVariables locales, parámetros del método.Lo que se utiliza es la pila de máquinas virtuales JVM.pilaMemoria
    7. Al llamar a un método, primero vaya aárea del métodoObtenga las instrucciones de código de bytes del método, medianteintérpreteInterpretar instrucciones de código de bytes en código de máquina para su ejecución.
    8. Al llamar a un método, lea el número de línea de instrucción ejecutadacontador de programa, si se produce un cambio de hilo, puede continuar desde la posición interrumpida al reanudar.
    9. Para llamadas a métodos no implementados en Java (métodos nativos), se llama al uso de memoriapila de métodos nativos(ver descripción); los métodos Java ordinarios utilizanPila de máquinas virtuales
    10. Para llamadas a métodos de punto de acceso o código que se repite con frecuencia, el JITCompilador justo a tiempoCompile estos códigos en la caché de código de máquina para mejorar el rendimiento de ejecución.

ilustrar

  • La fuente en negrita representa los componentes de la máquina virtual JVM
  • Para la implementación de la máquina virtual Hotspot de Oracle, no hay distinción entre la pila de máquinas virtuales y la pila de métodos locales.

Áreas donde puede ocurrir un desbordamiento de la memoria (agotamiento de la memoria)

  • Áreas donde no se producirá un desbordamiento de la memoriacontador de programa
  • Se produce OutOfMemoryError (error de falta de memoria)
    • Memoria del montón agotada– Cada vez hay más objetos, se utilizan todo el tiempo y no se pueden recoger como basura.
    • Memoria del área de método agotada– Se cargan cada vez más clases y muchos marcos generarán dinámicamente nuevas clases durante el tiempo de ejecución.
    • Acumulación de pila de máquinas virtuales– Cada subproceso ocupará hasta 1 M de memoria, y el número de subprocesos aumentará y se ejecutará durante mucho tiempo sin ser destruido.
  • Área donde ocurre StackOverflowError
    • Pila de máquina virtual JVM, el motivo es que la llamada recursiva al método (en el subproceso) no finalizó correctamente (Demasiadas llamadas a métodos)、Referencia circular al deserializar json

Área de método, generación permanente, metaespacio.

  • Área del método : (Es una norma, es una definición.) es un área de memoria definida en la especificación JVM.utilizado para almacenar clasesMetadatos, código de bytes del método, información requerida por el compilador justo a tiempo, etc.
  • Generación permanente : (Implementación del área de métodos en diferentes versiones de Java.) es la implementación de la máquina virtual Hotspot de la especificación JVM (antes de 1.8)
  • Metaespacio : (Implementación del área de métodos en diferentes versiones de Java.) es otra implementación de la especificación JVM por parte de la máquina virtual Hotspot (posterior a 1.8),Utilice la memoria local como espacio de almacenamiento para esta información.

sólo presentarmetaespacio
Insertar descripción de la imagen aquí

Aprende tres cosas de esta imagen.

  • Cuando una clase se utiliza por primera vez, escargador de clasesLea la metainformación de clase del archivo de clase y guárdela en el metaespacio
  • La metainformación de clase de X e Y se almacena en el metaespacio y no se puede acceder a ella directamente.
  • Puede utilizar X.class, Y.class (instancia) para acceder indirectamente a la metainformación de la clase, ambos pertenecen a objetos java y pueden usarse en nuestro código

Insertar descripción de la imagen aquí

¿Qué se puede aprender de esta imagen?

  • En la memoria del montón: cuando no se hace referencia a todos los objetos de instancia correspondientes a todos los objetos de clase cargados por un objeto del cargador de clases , la memoria del montón ocupada por ellos se liberará durante la GC.
  • En el metaespacio: la liberación de memoria se realiza en unidades del cargador de clases . Cuando se libera la memoria del cargador de clases en el montón, también se liberará la metainformación de clase correspondiente en el metaespacio.

2.Parámetros de memoria JVM

Requerir

  • Familiarizarse con los parámetros comunes de JVM, especialmente aquellos relacionados con el tamaño.

Memoria de montón, configurada por tamaño

Insertar descripción de la imagen aquí

explicar:

  • -Xms Memoria de montón mínima(Incluyendo nueva generación y vieja generación)
  • -Xmx Memoria de montón máxima(Incluyendo nueva generación y vieja generación)
  • Por lo general, se recomienda configurar -Xms y -Xmx para que tengan el mismo tamaño, es decir, no es necesario reservar memoria ni crecer de pequeño a grande, por lo que el rendimiento es mejor.
  • -XX: NewSizey -XX:MaxNewSize Establecer los valores mínimo y máximo de la nueva generación., pero generalmente no se recomienda configurarlo, está controlado por la propia JVM.
  • -Xmnconfiguraciónmemoria de nueva generación, equivalente a configurar -XX:NewSize y -XX:MaxNewSize al mismo tiempoy tienen valores iguales
  • Retener significa que no ocupará tanta memoria al principio, a medida que se use más memoria, esta parte de la memoria reservada se irá usando gradualmente. Lo mismo abajo

Memoria de montón, configurada proporcionalmente
Insertar descripción de la imagen aquí

explicar:

  • -XX: NewRatio=2:1 significaVieja generación: Nueva generación;(El valor predeterminado es 2:1
  • -XX: SurvivorRatio=4:1 (Jardín del Edén: desde); significa que la nueva generación está dividida en seis partes, el Jardín del Edén ocupa cuatro partes, y desde y hacia cada uno ocupa una parte; (El valor predeterminado es 8:1
  • from = to
  • Survivor = from + to

P:
Con respecto a los parámetros de configuración de la memoria JVM: -Xmx10240m -Xms10240m -Xmn5120m -XX:SurvivorRatio=3 el valor mínimo de memoria y el tamaño total del área Survivor son respectivamente

  • Valor mínimo de memoria: -Xmn dividido por 5;
  • El tamaño total del área de Superviviente = de + a = -Xmn dividido por 5 y luego multiplicado por 2;

Configuración de la memoria del metaespacio
Insertar descripción de la imagen aquí

explicar:

  • class spaceInformación básica de la clase de almacenamiento, el valor máximo está controlado por -XX:CompressedClassSpaceSize
  • non-class spaceAlmacene otra información además de la información básica de la clase (como el código de bytes del método, anotaciones, etc.)
  • El tamaño total del espacio de clase y del espacio que no es de clase está -XX:MaxMetaspaceSizecontrolado por , el valor predeterminado es 1G

Aviso:

  • Aquí -XX: CompressedClassSpaceSize, este espacio también está relacionado con si la compresión del puntero está activada. No entraremos en detalles aquí. Simplemente puede pensar que la compresión del puntero está activada de forma predeterminada.

Configuración de la memoria caché de código
Insertar descripción de la imagen aquí

explicar:

  • Si -XX:ReservedCodeCacheSize < 240m, todo el código de máquina optimizado existe junto indiscriminadamente
  • De lo contrario, se divide en tres áreas (hay un error tipográfico en la imagen, el método está escrito incorrectamente y falta una e)
    • non-nmethods- Código utilizado por la propia JVM
    • profiled nmethods- Código de máquina parcialmente optimizado
    • non-profiled nmethods- Código de máquina totalmente optimizado

Configuración de la memoria del subproceso
La memoria ocupada por cada subproceso (pila de máquina virtual);
Insertar descripción de la imagen aquí

Documento oficial de referencia

  • https://docs.oracle.com/en/java/javase/11/tools/java.html#GUID-3B1CE181-CD30-4178-9602-230B800D4FAE

3.recolección de basura JVM

Requerir

  • Domina el algoritmo de recolección de basura.
  • Domina la idea del reciclaje generacional
  • Comprender el procesamiento de marcas de tres colores y marcas faltantes
  • Aprenda sobre los recolectores de basura comunes

Tres algoritmos de recolección de basura.

Método de marcar y barrer (ya no se utiliza, tiene muchos problemas de fragmentación)
Insertar descripción de la imagen aquí

explicar:

  1. Buscar GC Root 对象(objetos raíz), es decir, aquellosObjetos que nunca serán reciclados,comoObjetos a los que hacen referencia las variables locales del método en ejecución y objetos a los que hacen referencia las variables estáticas
  2. marcar etapa:A lo largo de la cadena de referencia del objeto GC Root, marque los objetos a los que se hace referencia directa o indirectamente.
  3. fase de limpieza: Libera la memoria ocupada por objetos sin etiquetar

Puntos clave:

  • La velocidad de marcado tiene una relación lineal con los objetos supervivientes.
  • La velocidad de borrado está linealmente relacionada con el tamaño de la memoria.
  • La desventaja es que provocará fragmentación de la memoria.

Método de clasificación de marcado (adecuado para la recolección de basura en la generación anterior)

Insertar descripción de la imagen aquí

explicar:

  1. La fase de marcado y la fase de limpieza anteriores son similares al método de marcado y limpieza.
  2. Hay un paso adicional de clasificación, moviendo los objetos supervivientes a un extremo para evitar la fragmentación de la memoria.

Características:

  • La velocidad de marcado tiene una relación lineal con los objetos supervivientes.
  • La velocidad de limpieza y clasificación está relacionada linealmente con el tamaño de la memoria.
  • La desventaja es que el rendimiento es más lento.

Método de copia marcada (adecuado para la recolección de basura en la nueva generación (menos objetos supervivientes))

Insertar descripción de la imagen aquí
explicar:

  1. Divida toda la memoria en dos áreas del mismo tamaño, desde y hacia, donde siempre está libre y desde almacena los objetos recién creados.
  2. La fase de marcado es similar al algoritmo anterior.
  3. Después de encontrar los objetos supervivientes, se copiarán del área de al área de A. La desfragmentación se completa naturalmente durante el proceso de copia.
  4. Una vez completada la copia, simplemente intercambie las posiciones de desde y hacia

Características:

  • Las velocidades de marcado y copia están relacionadas linealmente con los objetos supervivientes.
  • La desventaja es que ocupa el doble de espacio.

GC y algoritmo de recopilación generacional.

GCEl propósito es lograrLiberación automática de memoria de objetos inútiles.Reduzca la fragmentación de la memoria y acelere la asignación

Puntos clave de la general:

  • El área de reciclaje esmemoria del montón, excluyendo la pila de máquinas virtuales
  • Para determinar objetos inútiles, utiliceAlgoritmo de análisis de accesibilidad, método de marcado de tres coloresMarcar objetos vivos y reciclar objetos no marcados
  • La implementación específica de GC se llamaRecolector de basura
  • GC utiliza principalmenteIdeas de reciclaje generacional
    • La base teórica es que la mayoría de los objetos van y vienen, se destruyen inmediatamente y pueden reciclarse inmediatamente después de su uso. También hay una pequeña cantidad de objetos que sobreviven durante mucho tiempo y son difíciles de reciclar cada vez.
    • Según las características de estos dos tipos de objetos, el área de reciclaje se divide ennueva generación(los objetos van y vienen) yvejez(Supervivencia, difícil de reciclar cada vez),La nueva generación utiliza el método de copia de marcas y la generación anterior generalmente utiliza el método de clasificación de marcas.
  • Según la escala de GC, se puede dividir en GC menor , GC mixto y GC completo.

    GC menor : la recolección de basura se ha producido en la nueva generación, que es una recolección de basura a pequeña escala;
    GC completa : tanto la nueva generación como la generación anterior tienen memoria insuficiente y se realizará una recolección de basura completa. Tomará mucho tiempo. se sentirán tiempo y pausas obvias en el sistema;
    GC mixto : la recolección de basura ocurre en la nueva generación y la recolección de basura también ocurre en algunas generaciones anteriores. Esto es exclusivo del recolector de basura G1;

Reciclaje generacional

  1. El Edén, donde se asignan inicialmente todos los objetos, y el área de supervivientes (dividida en desde y hacia) se denominan colectivamente la nueva generación.

Insertar descripción de la imagen aquí

  1. Cuando Eden se quede sin memoria, marque los objetos supervivientes de Eden y de (actualmente ninguno)

Insertar descripción de la imagen aquí

  1. Utilice el algoritmo de copia para copiar los objetos supervivientes a. Una vez completada la copia, tanto el Edén como los recuerdos se liberan.

Insertar descripción de la imagen aquí

  1. Intercambiar desde y hacia

Insertar descripción de la imagen aquí

  1. Después de un período de tiempo, la memoria de Eden vuelve a ser insuficiente.

Insertar descripción de la imagen aquí

  1. Marque los objetos supervivientes del Edén y de

Insertar descripción de la imagen aquí

  1. Copie los objetos supervivientes usando el algoritmo de copia.

Insertar descripción de la imagen aquí

  1. Después de copiar, tanto el Edén como la memoria se liberan.

Insertar descripción de la imagen aquí

  1. Intercambiar desde y hacia

Insertar descripción de la imagen aquí

  1. Generación anterior: cuando el objeto del área de sobreviviente sobrevive a varios reciclajes (hasta 15 veces), se promueve a la generación anterior (la memoria insuficiente en el área de sobreviviente o los objetos grandes conducirán a una promoción temprana)

escala GC

  • Minor GCLa recogida de basura se produce en la nueva generación, con cortos tiempos de pausa
  • Mixed GCRecolección de basura en partes de nueva generación + generación anterior, exclusiva del recolector G1
  • Full GCSe debe evitar en la medida de lo posible la recolección completa de basura de nueva generación + generación anterior y tiempos de pausa prolongados.

marca tricolor

Es decir, se utilizan tres colores para registrar el estado de marcado del objeto.

  • Negro – marcado
  • Gris – Marcado
  • Blanco – aún no marcado
  1. Los primeros tres objetos aún no se han procesado y se muestran en gris.
efecto de edición de texto predeterminado de Android
  1. La referencia del objeto ha sido procesada y se muestra en negro. El objeto referenciado en negro se vuelve gris.
efecto de edición de texto predeterminado de Android
  1. Etcétera
efecto de edición de texto predeterminado de Android
  1. Marcado a lo largo de la cadena de referencia.
efecto de edición de texto predeterminado de Android
  1. El último objeto blanco sin marcar es basura.
efecto de edición de texto predeterminado de Android

Problema de oferta simultánea faltante

Los recolectores de basura más avanzados admiten el marcado concurrente , es decir, los subprocesos del usuario aún pueden funcionar durante el proceso de marcado. Pero esto trae un nuevo problema: si el hilo del usuario modifica la referencia del objeto, habrá un problema de marca faltante. Por ejemplo:

  1. Trabajo de marcado no completado como se muestra
    efecto de edición de texto predeterminado de Android

  2. El hilo del usuario está trabajando al mismo tiempo y desconecta la referencia entre los dos objetos 3 y 4 en la primera capa. En este momento, para el hilo de recolección de basura que está procesando el objeto 3, considerará el objeto 4 como basura blanca.
    efecto de edición de texto predeterminado de Android

  3. Pero si otros subprocesos de usuario establecen referencias a los objetos 2 y 4, debido a que el objeto 2 es un objeto procesado en negro, el subproceso de recolección de basura no notará el cambio en la relación de referencia, lo que resultará en una marca perdida.
    efecto de edición de texto predeterminado de Android

  4. Si el hilo del usuario permite que el objeto negro haga referencia a un nuevo objeto, todavía habrá un problema de marca faltante.
    efecto de edición de texto predeterminado de Android

Por lo tanto, para el marcado concurrente , se debe resolver el problema del marcado faltante, es decir,Para registrar cambios durante el proceso de calificación.. Hay dos soluciones:

  1. Incremental Update Método de actualización incremental, el recolector de basura CMS utiliza
    • La idea es interceptar cada acción de asignación, mientras se produzca la asignación, el objeto asignado será registrado y confirmado nuevamente durante la fase de remarcación.
  2. Snapshot At The Beginning, SATBmétodo de instantánea original, el recolector de basura G1 usa
    • La idea es interceptar cada acción de asignación, pero los objetos registrados son diferentes y estos objetos deben procesarse dos veces en la etapa de remarcación.
    • Nuevo objetoserá grabado
    • El objeto cuya relación de referencia fue eliminada.también grabado

Recolector de basura -Parallel GC

  • El GC menor ocurre cuando eden se queda sin memoria, utiliza un algoritmo de copia marcada y necesita suspender el hilo del usuario.
  • Antiguo: se produce GC completo debido a memoria insuficiente. Se utiliza un algoritmo de marcado y clasificación y los subprocesos del usuario deben pausarse.
  • Centrarse en el rendimiento

Recolector de basura:ConcurrentMarkSweep GC (escaneo de marcas simultáneo, con fragmentación de basura)

  • Es un recopilador que funciona en la era antigua, admite marcado concurrente y utiliza un algoritmo de limpieza concurrente .

    • No es necesario pausar los hilos de los usuarios durante el marcado simultáneo
    • El hilo del usuario aún debe pausarse al volver a marcar
  • Si falla la concurrencia (es decir, la velocidad de reciclaje no puede seguir el ritmo de la velocidad de creación de nuevos objetos), se activará Full GC.

  • Centrarse en el tiempo de respuesta

Recolector de basura -G1 GC (recolector predeterminado de JDK)

  • Equilibre el tiempo de respuesta y el rendimiento
  • Dividida en múltiples áreas, cada área puede servir como edén, sobreviviente, viejo, enorme, entre los cuales el enorme está especialmente preparado para objetos grandes.
  • Dividido en tres etapas: recolección de nueva generación, marcado concurrente y recolección mixta.
  • Si falla la concurrencia (es decir, la velocidad de reciclaje no puede seguir el ritmo de la velocidad de creación de nuevos objetos), se activará Full GC.

Etapa de reciclaje G1: reciclaje de nueva generación

  1. Inicialmente, todas las áreas están inactivas.
efecto de edición de texto predeterminado de Android
  1. Creé algunos objetos y seleccioné algunas áreas libres como Eden Garden para almacenar estos objetos.
efecto de edición de texto predeterminado de Android
  1. Cuando Eden necesite recolección de basura, seleccione un área libre como área sobreviviente y use el algoritmo de copia para copiar los objetos sobrevivientes, lo que requiere pausar el hilo del usuario.
efecto de edición de texto predeterminado de Android
  1. La copia se completa y se libera la memoria anterior de Eden.
efecto de edición de texto predeterminado de Android
  1. A medida que pasa el tiempo, el recuerdo del Edén se vuelve insuficiente.
efecto de edición de texto predeterminado de Android
  1. Copie los objetos supervivientes en Eden y el área de supervivientes anterior a la nueva área de supervivientes utilizando un algoritmo de copia, y los objetos más antiguos se promoverán a la generación anterior.
efecto de edición de texto predeterminado de Android
  1. Libera la memoria del Edén y el área de supervivientes anterior.
efecto de edición de texto predeterminado de Android

Fase de recogida G1: marcado simultáneo y recogida mixta

  1. Cuando la memoria ocupada por la generación anterior excede el umbral, se activa la marca concurrente y no es necesario pausar el hilo del usuario.
efecto de edición de texto predeterminado de Android
  1. Después del marcado concurrente, habrá una fase de remarcado para resolver el problema de la marca faltante. En este momento, el hilo del usuario debe pausarse. Una vez completado todo esto, sabrá qué objetos supervivientes pertenecen a la generación anterior.

(Luego se ingresa a la fase de recolección mixta. En este momento, todas las áreas de generación anterior no se reciclarán, pero las áreas con alto valor (menos objetos sobrevivientes) se reciclarán primero según el objetivo de tiempo de pausa (este también es el origen de la nombre Gabage Primero).)

efecto de edición de texto predeterminado de Android
  1. En la fase de recolección mixta, Eden, Survivor y Old participan en la replicación. La siguiente figura muestra la replicación de los objetos supervivientes en Eden y el área de Supervivientes.
efecto de edición de texto predeterminado de Android
  1. La siguiente figura muestra la replicación de objetos supervivientes promovidos en el área de generación anterior y superviviente.
efecto de edición de texto predeterminado de Android
  1. La copia está completa y se libera la memoria. Entrando a la siguiente ronda de recolección de nueva generación, marcado simultáneo y recolección mixta
efecto de edición de texto predeterminado de Android

4.desbordamiento de memoria

Requerir

  • Ser capaz de nombrar varias situaciones típicas que provocan un desbordamiento de la memoria.

Situaciones típicas [Pregunta de la entrevista: ¿En qué circunstancias se producirá un desbordamiento de memoria en el proyecto y cómo solucionarlo]

  • Desbordamiento de memoria causado por el mal uso del grupo de subprocesos

    • referenciaday03.TestOomThreadPool
    • Uso indebido de grupos de subprocesos de tamaño fijo: Demasiadas tareas hacen que la cola del grupo de subprocesos se llene, lo que provoca un desbordamiento de la memoria;
    • Uso indebido del grupo de subprocesos almacenados en búfer: Dado que no hay un límite superior en la cantidad de subprocesos, la cantidad de subprocesos agota los recursos del sistema, lo que provoca un desbordamiento de la memoria;
    • Solución: No utilice Executorsel new FixedThreadPool()método integrado con grupo de subprocesos fijos ni new CachedThreadPoll()el método con grupo de subprocesos de búfer integrado; debe controlar qué cola usar para la cola y establecer el límite superior usted mismo;
  • Desbordamiento de memoria causado por consultar demasiados datos

    • referenciaday03.TestOomTooManyObject
    • Consultar demasiados datos a la vez provoca un desbordamiento de la memoria: Por ejemplo, en una plataforma de comercio electrónico, cada vez que un usuario realiza una consulta, todavía hay 1 millón de productos. Si el volumen total de datos es de 363 Mb, los datos serán extremadamente grandes cuando varios usuarios realicen consultas y la memoria del servidor se agotará. ;
    • Solución:Al consultar todo, puede agregar condiciones de consulta. Lo más importante es limitlimitar el número máximo de registros devueltos. No devuelva demasiados registros en una consulta, de lo contrario es fácil agotar la memoria del servidor;
  • Desbordamiento de memoria causado por clases generadas dinámicamente

    • referenciaday03.TestOomTooManyClass
    • Herramienta para generar clases dinámicamente, preste atención al uso correcto, para evitar generar demasiadas clases que no se puedan liberar, lo que provocaría el agotamiento de la memoria del metaespacio;
    • Insertar descripción de la imagen aquí
    • Insertar descripción de la imagen aquí

5.carga de clases

Preguntas de entrevista:Proceso de carga de clasesDelegación parental
Requerir

  • maestrofase de carga de clases
  • Cargadores de clase magistral
  • entenderMecanismo de delegación de padres

Tres etapas del proceso de carga de clases.

  1. carga

    1. será similarÁrea del método de carga de código de bytesy crearobjeto clase.clase(El objeto de clase está en el montón)
    2. Si la clase principal de esta clase no está cargada,Cargar la clase principal primero
    3. La carga esejecución perezosa(La carga se activará solo cuando se use la clase)
  2. Enlace

    1. verificar-verificarSi la clase cumple con las especificaciones de la clase, la legalidad y los controles de seguridad.
    2. Prepararse paraLas variables estáticas (estáticas) asignan espacio y establecen valores predeterminados
    3. Analizando –Resolver referencias de símbolos de grupo constante a referencias directas
  3. inicialización

    1. implementarBloques de código estático (incluidas variables estáticas)yvariables estáticas no finalesAsignación de
    2. estática finalmodificada基本类型La asignación de variables se completa durante la fase de enlace.
    3. la inicialización esejecución perezosa(Inicializado solo cuando se usa)

Medios de verificación

  • Utilice jps para ver el número de proceso.
  • Utilice jhsdb para depurar y ejecutar el comando jhsdb.exe hsdbpara abrir su interfaz gráfica
    • Class BrowserPuede comprobar qué clases están cargadas en la jvm actual.
    • Utilice el universecomando de la consola para ver el rango de memoria del montón
    • Utilice el g1regiondetailscomando de la consola para ver regionlos detalles (región)
    • scanoops 起始地址 结束地址 对象类型Puede encontrar la dirección del objeto en un rango determinado según el tipo
    • El comando de la consola inspect 地址puede ver los detalles del objeto correspondiente a esta dirección.
  • Utilice el comando javap para ver el código de bytes de la clase

Descripción del código

  • day03.loader.TestLazy- La carga de clases de verificación es diferida y la carga de clases se activa solo cuando se usa.
  • day03.loader.TestFinal- Verificar que las variables modificadas con final no activen la carga de clases

Cargador de clases para jdk 8

nombre Que clase cargar ilustrar
Cargador de clases Bootstrap(Iniciar cargador de clases JAVA_HOME/jre/lib Sin acceso directo
Cargador de clases de extensión (cargador de clases de extensión JAVA_HOME/jre/lib/ext El nivel superior es Bootstrap, que se muestra como nulo.
Cargador de clases de aplicaciones (Cargador de clases de aplicaciones ruta de clases El superior es Extensión
Cargador de clases personalizado personalizar El padre es Aplicación

Mecanismo de delegación de padres

Así llamadoDelegación parental, se refiere a delegar prioridad al cargador de clase superior para la carga. Si el cargador de clase superior

  • Esta clase puede ser encontrada y cargada por el superior. Después de la carga, la clase también es visible para el cargador de nivel inferior.
  • Si no se puede encontrar esta clase, el cargador de clases de nivel inferior está calificado para realizar la carga.

El propósito de la delegación de los padres es doble

  1. Deje que las clases en el cargador de clases superior se compartan con los subordinados (no al revés), para que las clases puedan depender de las clases principales proporcionadas por jdk.
  2. Deje que la carga de clases tenga prioridad y asegúrese de que las clases principales se carguen primero

Malentendidos sobre la delegación de los padres

La respuesta a la siguiente pregunta de la entrevista es incorrecta.

Insertar descripción de la imagen aquí

¿Qué ocurre?

  • ¿Puedo cargar un java.lang.System falso escribiendo mi propio cargador de clases? La respuesta es no.

  • Suponiendo que su propio cargador de clases utiliza delegación parental, el cargador de clases de inicio cargará primero el java.lang.System real y, naturalmente, el falso no se cargará.

  • Suponiendo que su propio cargador de clases no usa la delegación parental, cuando su cargador de clases carga el java.lang.System falso, primero necesita cargar la clase principal java.lang.Object, pero no usa la delegación y no puede encontrar java. .lang.Object por lo que la carga fallará

  • Lo anterior son sólo suposiciones . De hecho, encontrará que cuando el cargador de clases personalizado carga una clase que comienza con java, generará una excepción de seguridad (no tiene turno para cargar porque hay una verificación de seguridad). En las versiones jdk9 y superiores, estos paquetes especiales Los nombres están relacionados con el módulo. Después de vincularlo, ni siquiera se puede compilar.

Descripción del código

  • day03.loader.TestJdk9ClassLoader: demuestra la relación vinculante entre los cargadores de clases y los módulos

6.Cuatro tipos de referencias

Pregunta de la entrevista: ¿Cuáles son los tipos de tipos de referencia de objetos?

Requerir

  • Domina los cuatro tipos de citas.

fuerte referencia

  1. La asignación de variables ordinarias es una referencia sólida, como A a = new A();
  2. A través de la cadena de referencia de GC Root,Si una referencia fuerte no puede encontrar el objeto, el objeto se puede reciclar.

Insertar descripción de la imagen aquí

Referencia suave

  1. Por ejemplo:SoftReference a = new SoftReference(new A());
  2. siCuando solo hay referencias suaves al objeto, el objeto no se reciclará para la primera recolección de basura . Si la memoria aún es insuficiente, el objeto no se liberará hasta que se recicle nuevamente.
  3. La referencia suave en sí debe liberarse junto con la cola de referencia.
  4. Un ejemplo típico son los datos de reflexión.
    Insertar descripción de la imagen aquí

Referencia débil

  1. Ejemplo:ReferenciaDébil a = nuevaReferenciaDébil(nueva A());
  2. Si solo se refieren al objeto referencias débiles, el objeto se liberará cada vez que se produzca la recolección de basura.
  3. La referencia débil en sí debe liberarse con la cola de referencia.
  4. Un ejemplo típico es el objeto Entry en ThreadLocalMap.

Insertar descripción de la imagen aquí

FantasmaReferencia

  1. Ejemplo: PhantomReference a = new PhantomReference(new A(), referenceQueue);

  2. Debe usarse junto con la cola de referencia . Cuando el objeto al que hace referencia la referencia virtual se recicla, el hilo Reference Handlerpondrá en cola el objeto de referencia virtual, para que pueda saber qué objetos se han reciclado y procesar aún más sus recursos asociados.

  3. Un ejemplo típico es Cleaner que libera la memoria directa asociada con DirectByteBuffer.

Insertar descripción de la imagen aquí

Descripción del código

  • day03.reference.TestPhantomReference: demuestra el uso básico de las referencias fantasmas
  • day03.reference.TestWeakReference: simula ThreadLocalMap, utiliza la cola de referencia para liberar memoria de entrada
package day03.reference;
// 前面讲的弱、虚引用配合引用队列,目的都是为了找到哪些 java 对象被回收,从而进行对它们关联的资源进行进一步清理
// 为了简化 api 难度,从 java 9 开始引入了 Cleaner 对象
public class TestCleaner1 {
    
    
    public static void main(String[] args) throws IOException {
    
    
        Cleaner cleaner = Cleaner.create();

        cleaner.register(new MyResource(), ()-> LoggerUtils.get().debug("clean 1")); //参数1关注的资源;参数2清理动作
        cleaner.register(new MyResource(), ()-> LoggerUtils.get().debug("clean 2"));
        cleaner.register(new MyResource(), ()-> LoggerUtils.get().debug("clean 3"));
        MyResource obj = new MyResource();  //局部变量;
        //下面的方法执行之前保持了强引用,则4不能被回收掉;
        cleaner.register(obj, ()-> LoggerUtils.get().debug("clean 4")); //4的清理动作不能被执行;
        cleaner.register(new MyResource(), ()-> LoggerUtils.get().debug("clean 5"));
        cleaner.register(new MyResource(), ()-> LoggerUtils.get().debug("clean 6"));

        System.gc();
        System.in.read(); //暂停的动作,因为cleaner是首部线程,当没有主线程执行时cleaner会自动结束,肉眼看不到效果;
    }

    static class MyResource {
    
    
    }
}

7.finalizar

Pregunta de la entrevista: Comprender
los requisitos para finalizar

  • Dominar el principio de funcionamiento y las deficiencias de finalizar.

finalizar
[ Pregunta de la entrevista: Comprensión de finalizar ]

  • [Respuesta general] Es un método en Object. Si una subclase lo anula, este método se llamará durante la recolección de basura y se podrán realizar la liberación y limpieza de recursos en él.
  • [ Excelente respuesta ]Es muy malo poner la liberación y limpieza de recursos en el método de finalización, lo que afecta en gran medida el rendimiento. En casos graves, incluso puede causar OOM (desbordamiento de memoria). Está marcado como @Deprecated desde Java9 y no se recomienda su uso. .

Código de prueba:

package day03.reference;
public class TestFinalize {
    
    
    static class Dog {
    
    
        private String name;

        public Dog(String name) {
    
    
            this.name = name;
        }

        @Override
        protected void finalize() throws Throwable {
    
    
            LoggerUtils.get().debug("{}被干掉了?", this.name);
            int i = 1 / 0;
        }
    }

    public static void main(String[] args) throws IOException {
    
    
        new Dog("大傻");
        new Dog("二哈");
        new Dog("三笨");
        System.gc();
        System.in.read();
    }
    /*
    第一,从表面上我们能看出来 finalize 方法的调用次序并不能保证(那个对象先回收,就调用那个对象的finalize 方法)
    第二,日志中的 Finalizer 表示输出日志的线程名称,从这我们看出是这个叫做 Finalizer 的线程调用的 finalize 方法
    第三,你不能注释掉 `System.in.read()`,否则会发现(绝大概率)并不会有任何输出结果了;
         (因为finalize线程是一个守护线程,如果主线程没有了,守护线程就不执行行了),
         从这我们看出 finalize 中的代码并不能保证被执行
    第四,如果将 finalize 中的代码出现异常,会发现根本没有异常输出;(调用了try...catch方法)
    第五,还有个疑问,垃圾回收时就会立刻调用  finalize 方法吗?
         不会,先把对象加入到ReferenceQueue,从 ReferenceQueue 中逐一取出每个 Finalizer 对象,把它们从链表断开,并真正调用 finallize 方法
     */
}

Resultados de:
Insertar descripción de la imagen aquí

principio final

  1. La lógica central para procesar el método de finalización se encuentra en la clase java.lang.ref.Finalizer, que contiene una variable estática (estructura de lista doblemente vinculada) llamada unfinalized. El finalizador también se puede considerar como otro objeto de referencia (estado y suave, débil y débil son equivalentes, pero no están expuestos al público y no pueden usarse directamente)
  2. Cuando se anula el objeto con el método de finalización, cuando se llama al método constructor, la JVM lo empaquetará en un objeto Finalizador y lo agregará a la lista vinculada no finalizada [En este momento, el método de finalización del objeto en la lista doblemente vinculada aún no ha sido llamado (cuando ocurra la recolección de basura) será llamado)】

Insertar descripción de la imagen aquí

  1. Hay otra variable estática importante en la clase Finalizer, la cola de referencia ReferenceQueue, que al principio está vacía. Cuando los objetos de perro se pueden recolectar como basura, los objetos Finalizador correspondientes a estos objetos de perro se agregarán a esta cola de referencia.
  2. Pero en este momento, el objeto Perro (el objeto asociado con Finalizador) no se puede reciclar de inmediato, porque la cadena de referencia de no finalizado -> Finalizador todavía hace referencia a él. Por el bien de [No se apresure a reciclarlo, esperar hasta que termine de ajustar el método de finalización y luego Reciclar]; si se recicla, no hay forma de llamar al método de finalización de estos objetos;
  3. El hilo FinalizerThread sacará cada objeto Finalizer uno por uno de ReferenceQueue, los desconectará de la lista vinculada y, de hecho, llamará al método de finalización.

Insertar descripción de la imagen aquí

  1. Dado que todo el objeto Finalizer se ha desconectado de la lista vinculada no finalizada, nadie puede hacer referencia a él ni al objeto perro, por lo que se reciclará en el próximo gc.

Desventajas de finalizar
[Por qué el método de finalización es muy malo y afecta el rendimiento]

muy mal

  • No se puede garantizar la liberación de recursos: FinalizerThread es un hilo de demonio. Es muy probable que el hilo finalice antes de que el código tenga tiempo de terminar de ejecutarse, lo que provocará que los recursos no se liberen correctamente.
  • No se puede determinar si ocurrió un error: Al ejecutar el método de finalización, se tragará cualquier excepción (Throwable), de modo que no se pueda juzgar si ocurrió un error al liberar recursos;

Afectar el desempeño

  • La memoria no se libera a tiempo.: El objeto con el método finalize anulado no puede liberar la memoria que ocupa a tiempo cuando se gc por primera vez, porque tiene que esperar a que FinalizerThread llame a finalize y lo elimine de la cola no finalizada antes de que pueda ser realmente gc'd. por segunda vez memoria libre;
  • Se puede imaginar que gc se debe a una memoria insuficiente y la llamada de finalización es muy lenta (las operaciones de eliminación de las dos colas se ejecutan en serie y no debería ser rápido liberar los recursos de la clase de conexión). se libera a tiempo y el objeto se libera. Si no es oportuno, pasará gradualmente a la generación anterior. Demasiada acumulación de basura en la generación anterior conducirá a un gc completo. Si la velocidad de liberación después del gc completo aún no se puede mantener Si aumentamos la velocidad de creación de nuevos objetos, se producirá OOM.

pregunta

  • Algunos artículos mencionan que [el subproceso Finalizer competirá con nuestro subproceso principal, pero debido a que tiene una prioridad más baja y requiere menos tiempo de CPU, nunca alcanzará al subproceso principal]. Esto obviamente es incorrecto. La prioridad de FinalizerThread es mayor. que el de los subprocesos ordinarios. La razón debería ser la lenta ejecución en serie de finalizar y otras razones (no debido a la baja prioridad)

Descripción del código

  • day03.reference.TestFinalize - código de prueba para finalizar

Supongo que te gusta

Origin blog.csdn.net/weixin_52223770/article/details/129006261
Recomendado
Clasificación