Acabado con tecnología Java (1) - Artículos de JVM

1. ¿Qué es JVM?

La JVM es una computadora virtual que puede ejecutar código Java, incluido un conjunto de instrucciones de código de bytes, un conjunto de registros, una pila, un recolector de basura, un montón y una pila de almacenamiento. La JVM se ejecuta sobre el sistema operativo y no interactúa directamente con el sistema operativo.


2. Proceso de operación:

Todos sabemos que los archivos fuente de Java, a través de compiladores, pueden generar archivos .class correspondientes, es decir, archivos de código de bytes, y los archivos de código de bytes se compilan en código de máquina en una máquina específica a través del intérprete en la máquina virtual de Java.

De la siguiente manera: archivo fuente de Java - compilador - archivo de bytecode - JVM - código de máquina

El intérprete de cada plataforma es diferente, pero la máquina virtual implementada es la misma, que es el mecanismo multiplataforma de Java.

  • Cuando se inician varios programas, habrá varias instancias de máquinas virtuales, que se crearán y destruirán con el inicio y la finalización del programa.
  • Los datos no se pueden compartir entre varias instancias de máquinas virtuales

2.1 Hilos

El subproceso aquí se refiere a una entidad de subproceso en el proceso de ejecución del programa, y ​​el subproceso de Java en Hotspot JVM tiene una relación de asignación directa con el subproceso del sistema operativo.

① Cuando el almacenamiento local del subproceso, la asignación del grupo de búfer, el objeto de sincronización, la pila, el contador del programa, etc. estén listos, cree un subproceso del sistema operativo, que cambia con el ciclo de vida del subproceso Java, y el sistema operativo es responsable de programar todos los subprocesos y asignación de CPU.
② El subproceso del sistema operativo completa la inicialización y llama run()al método del
subproceso de Java ③ Cuando finaliza el subproceso de Java, libere el subproceso del sistema operativo vinculado y todos los recursos del subproceso.

El subproceso principal del sistema que se ejecuta en segundo plano de Hotspot JVM

  • Subproceso de máquina virtual: se produce la espera de que la JVM alcance el punto seguro. Estas operaciones deben realizarse en un subproceso separado, ya que la JVM debe alcanzar el punto seguro cuando se modifica el almacenamiento dinámico. Las operaciones incluyen principalmente la recolección de elementos no utilizados para detener el mundo , el volcado de la pila de subprocesos , la suspensión de subprocesos y la liberación de bloqueo de polarización de subprocesos .
  • Hilo de tareas periódicas: responsable de las tareas del temporizador (es decir, interrupciones), utilizado para programar la ejecución de operaciones periódicas.
  • Subproceso de GC: Admite varias actividades de GC de la JVM.
  • Subproceso del compilador: admite la compilación dinámica de código de bytes en código de máquina nativo dependiente de la plataforma en tiempo de ejecución.
  • Subproceso de distribución de señales: admite la recepción de señales enviadas a la JVM y la llamada a los métodos JVM apropiados para su procesamiento.

2.2 Modelo de memoria JMM

  • Área de memoria privada: el ciclo de vida es el mismo que el de los subprocesos, dependiendo de la creación o el final de los subprocesos de usuario (en Hotspot JVM, cada subproceso se asigna directamente a los subprocesos del sistema operativo)
    • Contador de programa: la única área donde no ocurre OOM
      • Un pequeño espacio de memoria es un indicador del número de línea de bytecode ejecutado por el subproceso actual, y cada subproceso tiene un contador de programa independiente.
      • Si se está ejecutando el método Java, el contador registra la dirección de la instrucción de código de bytes (la dirección de la instrucción actual) y se establece en vacío si se trata de un método nativo (Método nativo).
    • Pila de máquina virtual: describe el modelo de memoria de la ejecución del método Java. Cuando se ejecuta cada método, se crea un marco de pila (Stack Frame) para almacenar la tabla de variables locales, la pila de operandos, el enlace dinámico, la salida del método y otra información.El marco de pila corresponde al proceso desde el principio hasta el final del método.
      • Marco de pila: es una estructura de datos que almacena datos y resultados de cálculos parciales. También se utiliza para procesar información como enlaces dinámicos, valores de retorno de métodos y envío de excepciones. No importa cómo se complete el método (normal o anormal), será destruido con el final del método.
    • Pila de métodos nativos: una estructura de pila que sirve a los métodos nativos.
  • Área de memoria compartida:
    • Área de método (generación permanente): almacena datos como información de clase cargada, constantes, variables estáticas y código compilado justo a tiempo.
      • Conjunto de constantes de tiempo de ejecución: una parte del área de métodos, utilizada principalmente para almacenar referencias literales y de símbolos generadas durante la compilación después de la carga de la clase.
    • Área de instancia de clase (memoria de montón): el área de memoria que almacena objetos y matrices creados, y es el área de memoria más importante para GC.
  • Área de memoria directa: no administrada por JVM GC

2.3 Memoria de tiempo de ejecución de JVM

Desde la perspectiva de GC, el montón de JVM se puede subdividir en la nueva generación y la generación anterior .

2.3.1 La nueva generación

La nueva generación ocupa 1/3 de la memoria del montón de JVM y la generación anterior ocupa 2/3 del espacio.

El área de nueva generación se puede dividir en tres partes: área Eden (8/10), área SurvivorFrom (1/10), área SurvivorTo (1/10)
- Área Eden: área de almacenamiento de nuevos objetos Java (si el nuevo objeto es demasiado grande, se colocará directamente en el área de generación anterior), cuando la memoria en esta área sea insuficiente, activará Minor GC para reclamar el área de nueva generación.
- Área SurvivorFrom: Guarda los objetos que no fueron reciclados en la última GC
- Área SurvivorTo: Guarda los objetos que no fueron reciclados por Minor GC una vez.

GC menor (recolección de basura menor)

  • Algoritmo de adopción: Algoritmo de copia
  • El proceso de MinorGC: copiar-borrar-intercambiar

El proceso de recolección de basura en la nueva generación:

  • 1. Copie eden y supervivienteDe a supervivienteA, y edad +1 para todos los objetos
    • Si la edad del objeto cumple con el estándar de la vejez, cópielo a la vejez
    • Si no hay suficiente memoria en el área SurvivorTo, se copiará directamente a la generación anterior
  • 2. Borrar las áreas de edon y superviviente.
  • 3. Los punteros SurvivorFrom y SurvivorTo se intercambian
    • En el siguiente GC, el SurvivorFrom actual es el SurvivorTo que debe escanearse

2.3.2 Vieja generación

La generación anterior almacena principalmente objetos de memoria de larga duración en la aplicación.Debido a que los objetos son estables, MajorGC no ocurre con frecuencia.

  • Cuando un objeto de nueva generación ingresa a la generación anterior, MajorGC se activa primero y luego MajorGC se activa.
  • MajorGC también se activa para hacer espacio cuando no puede encontrar suficiente espacio de memoria para asignar a objetos más grandes recién creados.
  • Cuando la memoria de la generación anterior es insuficiente, se lanza una excepción OOM.

Major GC (Gran Recolección de Basura)

  • Algoritmo utilizado: algoritmo mark-and-sweep.
  • El proceso de uso después de que se activa la generación anterior:
    • 1. Escanee todos los objetos de la generación anterior y marque los objetos supervivientes.
    • 2. Reciclar objetos sin marcar.
  • Desventajas: cada recuperación generará fragmentos de memoria, que generalmente deben fusionarse o marcarse para facilitar la siguiente asignación directa.

2.3.3 Generación permanente

El área de memoria permanente almacena principalmente información de Clase y Meta (metadatos).

  • La clase se coloca en el área de generación permanente cuando se carga, y el GC no reciclará el área permanente cuando se esté ejecutando el programa principal, por lo que provocará una excepción OOM.

Espacio de metadatos: Java 8 introduce el espacio de memoria para reemplazar la generación permanente. La mayor diferencia es que el espacio de metadatos se asigna en la memoria real y su tamaño también se limita a la memoria disponible real; mientras que la generación permanente se asigna en la memoria de la JVM, limitada por la JVM.


2.4 Algoritmo de recolección de basura

2.4.1 ¿Cómo juzgar si es basura?

  • Método de conteo de referencia: se hace referencia al objeto una vez y el contador de referencia es + 1. Cuando el número de referencia es 0 o el número de referencia es el más bajo entre todos los objetos, GC lo reciclará.
  • Análisis de accesibilidad: al buscar una serie de objetos de "raíces de GC" como punto de partida, cuando no hay una ruta alcanzable entre una "raíz de GC" y un objeto, el objeto es inalcanzable y está marcado , si el segundo La segunda marca de búsqueda sigue siendo un objeto inalcanzable, y será reclamado por GC.

2.4.2 ¿Qué algoritmos de GC existen?

  • Algoritmo Mark-Sweep (Mark-Sweep): uno de los algoritmos de GC más básicos, dividido en dos fases: marcar y borrar. Su desventaja es la fragmentación de la memoria .
    • Etiquetado: Etiquete objetos reciclables con un solo escaneo.
    • Borrar: Reciclar objetos marcados.
  • Algoritmo de copia (copia): divida la memoria en dos partes de igual tamaño (área principal y área de respaldo), primero use el área principal, y cuando la memoria en el área principal esté llena o no sea suficiente para asignar suficiente espacio, el área principal se marcará y borrará para su reciclaje, y luego copiará los objetos sobrevivientes en el área de respaldo y limpiará el área principal. La desventaja es que la memoria disponible se reduce a la mitad, hay demasiados objetos sobrevivientes y la eficiencia del algoritmo de copia disminuye.
  • Algoritmo Mark-Compact (Mark-Compact): dividido en tres etapas: etiquetado, movimiento y limpieza.
    • Etiquetado: Marcar objetos reciclables.
    • Mover: Mueva los objetos sobrevivientes a un extremo de la memoria.
    • Borrar: Limpia todas las áreas fuera del área de almacenamiento de objetos supervivientes.
  • Algoritmo de recopilación generacional: principalmente para la nueva generación, la generación anterior y el algoritmo de recopilación de generación permanente.
    • La nueva generación: usando el algoritmo de replicación
      • Dado que la operación de limpieza de la nueva generación es más que la operación de copia, generalmente se divide en un área de Edon más grande y dos espacios de Superviviente más pequeños. Al realizar GC, copie los objetos sobrevivientes en el área de Eden y uno de los espacios de Superviviente a otro. Superviviente en el espacio.
    • Generación anterior: uso del algoritmo de replicación de marcas
      • Cuando la edad del objeto alcanza los 15 años, se elimina de la generación anterior.
    • Generación permanente: uso del algoritmo de copia de marca
      • Recoge principalmente constantes obsoletas y clases inútiles

2.5 Los cuatro tipos de referencia de Java

  • Referencia fuerte: más comúnmente utilizada en variables de asignación de objetos, esta referencia es una referencia fuerte, no será reciclada por la JVM, que es la principal causa de OOM.
  • Referencia suave: implementada a través de la clase SoftReference. Para los objetos de referencia suave, solo se reciclarán cuando la JVM se quede sin memoria. Se usa comúnmente en programas sensibles a la memoria.
  • Referencia débil: implementada por la clase WeakRefrence, siempre que se inicie el mecanismo de GC, la referencia de clase se reciclará y, a menudo, se usa para la inicialización de clases (como bloques de código de clase).
  • Referencia fantasma: implementada a través de la clase PhantomRefrence, debe usarse junto con la cola de referencia y se usa principalmente para rastrear el estado del objeto que se recicla.

2.6 La diferencia entre el algoritmo de recopilación generacional y el algoritmo de recopilación de partición

2.6.1 Algoritmo de recolección generacional

  • Algoritmo de replicación de nueva generación: cuando la GC ocurre con frecuencia y solo quedan unos pocos objetos, se selecciona el algoritmo de replicación y el costo es menor.
  • Algoritmo de clasificación y marcado de generación anterior: la tasa de supervivencia de los objetos es alta y se selecciona el algoritmo de marcado y clasificación, que es más eficiente

2.6.2 Algoritmo de recopilación de particiones

  • El algoritmo de partición consiste en dividir una parte del espacio de memoria en diferentes espacios de memoria continuos. Cada área pequeña se puede usar de forma independiente y recuperar de forma independiente. Puede controlar varios espacios para recuperarlos al mismo tiempo. De acuerdo con la diferencia del tiempo de pausa objetivo, varias áreas pequeñas pueden recuperarse razonablemente cada vez, reduciendo así la pausa generada por un GC.

Recolector de basura 2.7 GC

Java proporciona diferentes recolectores de basura para la nueva generación y la generación anterior.

  • nueva generación
    • Serial (algoritmo de copia de un solo subproceso): uno de los recolectores de basura más básicos, que es el único GC de nueva generación antes de JDK 1.3.1. Solo usa un subproceso o una CPU durante la ejecución y bloquea todos los subprocesos hasta que se completa la recolección de basura . Debido a sus características de alta eficiencia, no hay sobrecarga de interacción de subprocesos en un entorno de CPU único limitado, por lo que Serial sigue siendo el recopilador de nueva generación predeterminado de la JVM en modo Cliente.
    • ParNew (serie de subprocesos múltiples): de forma predeterminada, la cantidad de subprocesos es la misma que la cantidad de CPU, y -XX:ParallelGCThreadsla cantidad de subprocesos del recolector de elementos no utilizados puede limitarse mediante parámetros.
    • Parallel Scavenge (Multi-thread Adaptive Serial): uso eficiente del tiempo de la CPU para la recolección de elementos no utilizados en un entorno de alto rendimiento. Es principalmente adecuado para la computación en segundo plano y tareas que no requieren demasiada interacción. La estrategia de ajuste adaptativo es su principal característica. .
  • vieja generación
    • CMS (barrido de marcas concurrente): al obtener el tiempo de pausa de recolección de basura más corto, se utiliza el algoritmo de barrido de marcas de subprocesos múltiples para la recolección de basura. El mecanismo de trabajo tiene cuatro etapas:
      • Marcado inicial: el marcado de objetos directamente asociados con las raíces de GC es extremadamente rápido y requiere el bloqueo de subprocesos de trabajo.
      • Marcado concurrente: Ejecutar operaciones de rastreo de raíces de GC simultáneamente con subprocesos de usuario
      • Reetiquetado: la corrección del etiquetado que cambia debido a la ejecución del programa del usuario requiere el bloqueo de subprocesos de trabajo
      • Limpieza concurrente: cuando tanto la primera marca como la segunda marca son reciclables, el CMS borra el objeto reciclable actual
    • Serial Old (algoritmo de finalización de marca de un solo subproceso): la versión antigua del recopilador Serial, que se ejecuta principalmente en el recolector de basura antiguo JVM predeterminado del cliente.
    • Parallel Old (Serial Old adaptativo de subprocesos múltiples): la versión de generación anterior del recopilador Parallel Scavenge, en un entorno de alto rendimiento, se usa con Parallel Scavenge para realizar estrategias de ajuste de recolección de basura de generación nueva/antigua.
  • Recolector G1: CMS mejorado, basado en el algoritmo de clasificación de marcas y control preciso del tiempo de pausa, al tiempo que garantiza un alto rendimiento y logra un GC de pausa baja, tiene la mayor eficiencia de recolección de basura dentro de un tiempo efectivo.
    • 1. Divida la memoria del montón en varias áreas de memoria de tamaño fijo y realice un seguimiento del progreso del GC de estas áreas
    • 2. Mantener una lista de prioridades, y dar prioridad a las áreas donde se genera basura con mayor frecuencia de acuerdo al tiempo de recolección permitido.

2.8 E/S y NIO

2.8.1 Modelo de E/S de bloqueo

Uno de los modelos IO más tradicionales, es decir, el bloqueo se produce durante la lectura y la escritura.

  • Concepto: el subproceso del usuario envía una solicitud de E/S y el kernel verifica el estado de preparación de los datos. Si los datos no están listos, el subproceso del usuario está en un estado bloqueado y el subproceso del usuario entrega la CPU. Cuando los datos están listos, el subproceso del usuario kernel copia los datos al subproceso del usuario y devuelve el resultado al subproceso del usuario.El subproceso del usuario desbloquea el estado.
  • Ejemplo: data = socket.read si los datos no están listos, siempre se bloquearán en el método de lectura.

2.8.2 Modelo de E/S sin bloqueo

  • Concepto: después de que el subproceso del usuario emite una operación de lectura, el kernel verifica el estado de preparación de los datos. Si los datos están listos, el kernel los copia. Si los datos no están listos, devuelve directamente un resultado de error. El subproceso del usuario sigue preguntando el núcleo sobre el estado de preparación de los datos, por lo que el modelo NIO siempre ocupará la CPU.
  • ejemplo: while(true){ data = socket.read(); if( data != error ) break; }
  • Desventajas: Alto uso de la CPU

2.8.3 Modelo de E/S de multiplexación

Actualmente, utilizando más modelos de IO, Java NIO es un IO multiplexado.

  • Concepto: en el modelo de E/S multiplexado, habrá un subproceso del kernel que sondeará continuamente el estado de cada conector, y la operación de E/S se llama solo cuando el conector envía una solicitud de E/S. En Java NIO, al selector.select()sondear el socket, si no hay una solicitud, se bloqueará en el estado de sondeo.
  • Escenario de uso: Es adecuado para escenarios con una gran cantidad de conexiones.
  • Desventaja: si el cuerpo de la respuesta es demasiado grande, bloqueará el procesamiento de otras solicitudes de IO y afectará el progreso del sondeo de sockect.

2.8.4 Modelo de E/S controlado por señal

  • Concepto: cuando el subproceso del usuario inicia una solicitud de E/S, registre una función de señal para el socket correspondiente y luego el subproceso del usuario continúa ejecutándose. Cuando los datos del núcleo estén listos, enviará una señal al subproceso del usuario. Cuando el subproceso del usuario recibe la señal, utiliza el IO de la función de señal Interfaz de operación para implementar operaciones de lectura y escritura.

2.8.5 Modelo de E/S asíncrono

Un modelo IO ideal.

  • Concepto: después de que el subproceso del usuario inicia una solicitud de lectura, no necesita esperar a que regresen los datos y, al mismo tiempo, realiza otras tareas. Desde la perspectiva del núcleo, asynchronous readdespués de que el núcleo lo reciba, regresará inmediatamente, lo que indica que la solicitud de lectura se inició con éxito, por lo que no se producirá ningún bloqueo. Después de que el núcleo espere a que los datos estén listos, los copiará a el subproceso de usuario y enviar una señal al subproceso de usuario.
  • Uso: en Java 7, se proporciona la clase AIO (E/S asíncrona).
  • Ventajas: el subproceso de usuario no necesita bloquear el subproceso durante la fase de solicitud de IO y la fase de uso de IO, pero puede usar directamente los datos después de recibir la señal enviada por el kernel.

2.9 Java IO包

Principalmente las ramas de flujo de bytes y flujo de caracteres de uso común.


2.10 Paquete Java NIO

NIO tiene tres partes principales principales: Canal (canal), Búfer (búfer), Selector (selector) .

NIO realiza operaciones de E/S basadas en el canal y el búfer. Los datos siempre se leen desde el canal al búfer o se escriben en el canal desde el búfer; mientras que el selector escucha múltiples eventos del canal (como conexión, datos listos), por lo que un solo hilo Puede escuchar varios pasillos.

La mayor diferencia entre NIO e IO es [IO orientado a flujo, NIO orientado a búfer]

  • **Búfer NIO**

La E/S tradicional lee uno o varios bytes de la secuencia hasta que se leen todos los bytes, por lo que los datos de la secuencia no se pueden preprocesar.

El establecimiento del búfer NIO es para preprocesar de manera flexible los datos leídos en el búfer. Cuando los datos se leen del canal al búfer, los datos leídos se pueden procesar en el búfer y luego se puede realizar la operación de adquisición de datos, pero el procesamiento Hay dos problemas que deben abordarse cuando se procesan datos: 1. Juzgar si los datos necesitan ser procesados ​​2. La lectura de datos nuevos no sobrescribe los datos no procesados .

  • No bloqueante de NIO

El no bloqueo de NIO significa que cuando un subproceso llama a una operación de lectura o escritura, obtendrá inmediatamente los datos disponibles actualmente o escribirá parte de los datos en el canal. Si no hay datos disponibles, devolverá datos vacíos sin esperar datos valiosos. , por lo que se puede usar NIO Los subprocesos separados administran múltiples canales IO.

  • Clases Java NIO

2.10.1 Canal

Channel y Stream en IO están al mismo nivel, excepto que Channel es bidireccional y Stream es unidireccional.

Las principales implementaciones de Channel en NIO son:

  • 1. FileChannel (archivo IO)
  • 2. DatagramChannel (canal UDP)
  • 3. SocketChannel (canal de cliente TCP)
  • 4. ServerSocketChannel (canal del servidor TCP)

2.10.2 Búfer

Buffer es en realidad una matriz continua.Cualquier dato leído o escrito debe transmitirse a través de Buffer, pero no es necesario que Buffer almacene en búfer entre canales.

Las principales implementaciones de Buffer en NIO son:

  • 1, búfer de bytes
  • 2, búfer corto
  • 3, IntBuffer
  • 4, búfer largo
  • 5, búfer doble
  • 6, búfer flotante
  • 7, búfer de caracteres

2.10.3 Selector

Selector puede detectar si se emite una solicitud de IO en varios canales registrados. Cuando hay una solicitud de IO, obtendrá el evento de solicitud y llamará al método de respuesta correspondiente al tiempo de solicitud.


2.11 Mecanismo de carga de clase JVM

El mecanismo de carga de clases JVM se divide en cinco partes:

  • Carga: en esta etapa, se generará en la memoria un objeto java.lang.Class que representa esta clase como entrada del área de método para leer varios datos de esta clase. (El objeto Clase aquí se puede leer desde el paquete comprimido, o puede ser una clase de proxy dinámico, o se puede generar a partir de otros archivos)
  • Verificación: esta etapa es para garantizar que la información contenida en el flujo de bytes del archivo Class cumpla con los requisitos de la JVM actual.
  • Preparación (Preparation): Esta etapa consiste en asignar memoria e inicializar variables de clase. (La inicialización aquí es el valor predeterminado del tipo que ha sido asignado por la JVM, por ejemplo, el valor de inicialización del tipo int es 0)
  • Resolución: esta etapa es el proceso de reemplazar referencias simbólicas en el conjunto constante con referencias directas. (Es decir, reemplace las posiciones donde se usan variables con constantes)
    • Referencia de símbolo: la referencia de símbolo no tiene nada que ver con el diseño de la implementación de la máquina virtual, pero la forma literal de la referencia de símbolo debe ajustarse al formato de archivo de clase de la especificación JVM.
    • **Referencia directa:** El objetivo al que se hace referencia debe existir en la máquina virtual. El objetivo al que se hace referencia directamente puede ser un puntero al objetivo, un desplazamiento relativo o un identificador para ubicar indirectamente el objetivo.
  • Inicialización (Initialization): Esta etapa consiste en ejecutar realmente el código del programa Java definido en la clase, principalmente el proceso de ejecución del <client>método constructor de la clase.
    • <client>El compilador combina el método para recopilar automáticamente la operación de asignación de la variable de clase en la clase y la instrucción en el bloque de instrucción estática. La JVM se asegurará de que la ejecución del constructor de la clase principal se complete antes de la ejecución del constructor de la subclase. Si no hay una variable estática en una clase, la asignación tampoco tiene un bloque de código estático, entonces el compilador no generará <client>métodos para ella.
    • Casos en los que no se realiza la inicialización de clases
      • 1. Cuando una subclase hace referencia al campo estático de la clase principal, solo activará la inicialización de la clase principal
      • 2. Se define una matriz de objetos.
      • 3. Clases que no hacen referencia directa a constantes
      • 4. Obtenga el objeto Clase por nombre de clase
      • 5. Al llamar a Class.forName() para cargar la clase especificada, especifique los parámetrosinitialize=false
      • 6. El método loadClass predeterminado de ClassLoader se llama

El mecanismo de descarga de las clases JVM se divide en dos partes:

  • Usando
  • Descarga

2.11.1 Cargadores de clase

La JVM proporciona tres cargadores de clases: cargador de clases de inicio, cargador de clases de extensión, cargador de clases de aplicación y cargador de clases personalizado.

  • Bootstrap ClassLoader: Responsable de cargar JAVA_HOME\libclases en el directorio, o en -Xbootclasspathla ruta especificada, y reconocido por la JVM (identificado por archivo, como rt.jar).
  • Extensión ClassLoader: Responsable de cargar la biblioteca de clases JAVA_HOME\liben el directorio o java.ext.dirsen la ruta especificada por la variable del sistema.
  • Application ClassLoader (Application ClassLoader): Responsable de cargar bibliotecas de clases en la ruta del usuario (classpath)
  • Cargador de clases personalizado: la JVM carga clases a través del modelo de delegación principal y puede java.lang.ClassLoaderimplementar un cargador de clases personalizado a través de la herencia.

2.11.2 Modelo de delegación de padres

  • Concepto: cuando una clase recibe una solicitud de carga de clases, primero delega la solicitud al cargador de clases principal, y cada cargador de clases delegará al cargador de clases principal, por lo que finalmente todas las solicitudes de carga de clases llegarán al cargador de clases de inicio. El cargador de clases responde que la solicitud no se puede procesar (la clase que se va a cargar no se puede encontrar en su propia ruta de carga), el cargador de clases secundario intenta cargarse solo.
  • Ventajas: Se garantiza que diferentes cargadores de clases eventualmente obtendrán el mismo objeto Object.

2.11.3 OSGI (Sistema de modelado dinámico)

OSGI proporciona la función de cambiar dinámicamente la estructura de varios dispositivos de red sin reiniciar, y puede realizar la función de intercambio en caliente a nivel de módulo. Cuando el programa se actualiza, solo algunos módulos del programa se pueden deshabilitar, reinstalar e iniciar. Mientras Al modularizar la funcionalidad, se introduce una alta complejidad adicional porque no se sigue el modelo de delegación parental.

Supongo que te gusta

Origin blog.csdn.net/Zain_horse/article/details/132137942
Recomendado
Clasificación