Comprensión profunda del mecanismo de recolección de basura de Java

1. Introducción

El mecanismo de recolección de elementos no utilizados de Java es uno de los componentes principales de la máquina virtual de Java (JVM) y desempeña un papel fundamental en la gestión de la memoria. Puede rastrear y administrar automáticamente los objetos creados en la aplicación.Cuando estos objetos ya no se usan, el mecanismo de recolección de basura reclamará automáticamente la memoria que ocupan, para que esta parte de la memoria pueda ser reutilizada. Este mecanismo reduce en gran medida la carga de los desarrolladores para administrar manualmente la memoria y evita las fugas de memoria causadas por negligencia.Es una ventaja significativa del lenguaje Java en comparación con otros lenguajes como C++.

Dos, estructura de memoria Java

La memoria de Java se divide principalmente en cinco áreas:

  1. Área de método : se utiliza para almacenar datos como información de clase, constantes y variables estáticas que ha cargado la máquina virtual.
  2. Heap : Java Heap es el área de memoria más grande administrada por la JVM. Casi todas las instancias de objetos y matrices deben asignarse en el montón. También se divide en dos partes, la generación joven y la generación anterior, para la asignación y el reciclaje eficientes de la memoria.
  3. Pila de máquina virtual (Java Stack) : cada hilo tiene una pila privada cuyo ciclo de vida está sincronizado con el hilo. El marco de pila almacena información como la tabla de variables locales, la pila de operandos, el enlace dinámico y la salida del método.
  4. Pila de métodos nativos : la pila de métodos nativos es similar a la pila de la máquina virtual, excepto que sirve al método nativo.
  5. Registro de contador de programa : es el indicador de número de línea del código de bytes ejecutado por el hilo actual.

Entre ellos, el área de método y el montón son las áreas principales en las que se enfoca el recolector de basura de Java, y también son el foco de nuestra próxima discusión.

3. ¿Qué es la basura?

En Java, el ciclo de vida de un objeto comienza desde la creación (nuevo) y finaliza cuando otros objetos ya no hacen referencia a él. En otras palabras, cuando un objeto no tiene ninguna referencia que lo apunte, el objeto se convierte en basura, esperando que el recolector de basura lo reclame. Vale la pena señalar que el objeto aún puede estar dentro del alcance, pero es imposible que el programa lo use nuevamente (por ejemplo: el objeto solo se usa en un alcance local), en este momento, el objeto también se considerará como basura. El trabajo principal del recolector de basura es encontrar estos objetos basura y liberar la memoria que ocupan, para proporcionar espacio para nuevos objetos.

4. Algoritmo de recolección de basura

1. Algoritmo Mark and Sweep (Mark and Sweep)

Este es el algoritmo de recolección de basura más básico. Se divide en dos fases: fase de marcado y fase de limpieza. La fase de marcado atraviesa todos los objetos para descubrir cuáles todavía están vivos. La fase de limpieza elimina todos los objetos sin marcar. Como se muestra en la imagen:
inserte la descripción de la imagen aquí

Aunque el algoritmo de marcar-borrar es muy intuitivo, hay dos problemas: uno es el problema de la eficiencia, la eficiencia de los dos procesos de marcar y borrar no es alta; el otro es el problema del espacio, una gran cantidad de fragmentos de memoria discontinuos ser generado después de borrar la marca.

2. Algoritmo de copia (Copia)

Para resolver el problema de eficiencia, se puede adoptar el algoritmo de "copia". El algoritmo de replicación divide la memoria disponible en dos bloques de igual tamaño según la capacidad, y solo usa uno de ellos a la vez. Cuando se agote esta parte de la memoria, copie el objeto sobreviviente a otra parte y luego limpie el espacio de memoria usado a la vez. De esta forma, se reclama una parte de la memoria cada vez y no hay necesidad de considerar la fragmentación de la memoria y otros problemas cuando se asigna la memoria. Como se muestra en la imagen:

inserte la descripción de la imagen aquí
Aunque el algoritmo de replicación es simple de implementar, tiene una alta eficiencia de memoria y no es propenso a la fragmentación, el mayor problema es que la memoria disponible se comprime a la mitad de la original y la memoria no se utiliza por completo. Y si aumenta la cantidad de objetos sobrevivientes, la eficiencia del algoritmo de replicación se reducirá considerablemente.

3. Marcar y compactar

Para resolver el problema del espacio, se puede utilizar un algoritmo de "clasificación de marcas". El proceso de marcado sigue siendo el mismo que el algoritmo de "eliminación de marcas", pero los pasos posteriores no limpian directamente los objetos reciclables, sino que permiten que todos los objetos sobrevivientes se muevan hacia un extremo y luego limpian directamente la memoria fuera del límite final. . Como se muestra en la imagen:
inserte la descripción de la imagen aquí

4. Colección Generacional

La recolección de basura actual de las máquinas virtuales comerciales adopta el algoritmo de "Recolección generacional". Este algoritmo divide el montón de Java en la nueva generación y la generación anterior, de modo que podamos adoptar el algoritmo de recopilación más adecuado según las características de cada época. En la nueva generación con una baja tasa de supervivencia de objetos, se puede seleccionar un algoritmo de copia y la colección se puede completar solo pagando una pequeña cantidad del costo de copia de los objetos supervivientes. En la generación anterior, debido a que el objeto tiene una alta tasa de supervivencia y no hay espacio adicional para asignarlo, podemos elegir el algoritmo "mark-clean" o "mark-compact" para la recolección de basura.

Tenga en cuenta que Java en sí mismo no proporciona una API para controlar directamente estos algoritmos de recolección de basura, son ejecutados automáticamente por la máquina virtual Java en segundo plano. Sin embargo, comprender estos algoritmos básicos de recolección de basura es la base para comprender técnicas de recolección de basura más avanzadas (como: recolección paralela, recolección concurrente, recolección incremental, etc.).

5. Recolector de basura

Java HotSpot VM incluye varios tipos de recolectores de basura, cada uno con sus propias características y adecuados para diferentes sistemas y escenarios de uso. incluir:

  • Recolector en serie: un recolector de subproceso único que debe suspender todos los demás subprocesos de trabajo hasta que termine de recolectar elementos no utilizados.
  • Recopilador paralelo: un recopilador de subprocesos múltiples que detiene todos los demás subprocesos de trabajo durante la recolección de elementos no utilizados hasta que finaliza la recolección.
  • Recolector CMS (Barrido de marcas concurrente): Recolector concurrente, su principal objetivo de diseño es evitar retrasos a largo plazo al recolectar basura en la vejez.
  • Recolector G1 (Garbage First): es un recolector de basura para aplicaciones del lado del servidor, que puede satisfacer las necesidades de tiempo de pausa predecible y alto rendimiento de recolección de basura.

Cabe señalar que cada recolector de basura tiene sus escenarios aplicables y no existe una distinción absoluta entre bueno y malo. En el diseño y desarrollo del sistema real, debemos seleccionar el colector más adecuado de acuerdo con las características de la aplicación (por ejemplo, si hay un requisito alto para el tiempo de respuesta del sistema, etc.) y los recursos de hardware.

6. Cuándo activar la recolección de basura

En Java, la JVM determina el momento de la recolección de elementos no utilizados. Aunque podemos System.gc()solicitar a la JVM que realice una recolección de basura llamando a un método, esto es solo una sugerencia, y la JVM puede optar por ignorar esta solicitud.

En la práctica, la JVM suele realizar la recolección de basura en las siguientes situaciones:

  • Cuando el espacio de memoria del montón de la JVM es insuficiente, la JVM activará la recolección de elementos no utilizados para liberar la memoria ocupada por objetos que ya no se usan, a fin de asignar espacio para nuevos objetos.
  • Cuando un espacio de generación anterior (Old Generation) está lleno, se activará un GC completo, lo que hará que todos los subprocesos de la aplicación Java se suspendan hasta que finalice el GC.
  • Cuando el sistema está inactivo, la JVM también puede optar por realizar una recolección de elementos no utilizados para mejorar la eficiencia del uso de la memoria del sistema.

El siguiente código Java mostrará cómo se realiza la recolección de basura durante el tiempo de ejecución:

public class GCDemo {
    
    
    public static void main(String[] args) {
    
    
        Runtime runtime = Runtime.getRuntime();
        long before = runtime.freeMemory(); //获取开始时JVM空闲内存
        for (int i = 0; i < 1000000; i++) {
    
    
            String s = new String("Hello, World!");
            s = null; // 显式地断开s的引用,使得s所指向的对象可以被垃圾回收
        }
        long after = runtime.freeMemory(); //获取结束时JVM空闲内存
        System.out.println("Memory freed by GC: " + (before - after));
    }
}

Este código generará la cantidad de memoria liberada por el recolector de basura, y puede ver que incluso si no activamos explícitamente la recolección de basura, la JVM realizará la recolección de basura en el momento apropiado.

epílogo

Comprender y dominar el mecanismo de recolección de basura de Java es crucial para escribir programas Java eficientes y estables. En este blog, presentamos los principios básicos del mecanismo de recolección de basura, la estructura de memoria de la JVM, el algoritmo de recolección de basura, varios recolectores de basura y el tiempo de activación de la recolección de basura. Aunque Java ya ha manejado la mayoría de los problemas de administración de memoria para nosotros, como desarrolladores de Java, todavía necesitamos comprender estos conceptos básicos para escribir un código más eficiente y evitar problemas como pérdidas de memoria. Espero que este blog sea útil para usted. Si tiene alguna pregunta, deje un mensaje para discutir.

Supongo que te gusta

Origin blog.csdn.net/weixin_46703995/article/details/131253783
Recomendado
Clasificación