Capítulo 10 Distribución de la memoria de instanciación de objetos y ubicación de acceso

Capítulo 10 Distribución de la memoria de instanciación de objetos y ubicación de acceso

JVM explicado por Song Hongkang de Shang Silicon Valley: enlace bilibili

1 instanciación de objetos

  • Preguntas de entrevista
    • Meituan
      • ¿Cómo se almacenan los objetos en la JVM?
      • ¿Qué hay en la información del encabezado del objeto?
    • Ant Financial
      • El segundo lado: ¿qué hay en el encabezado del objeto java?

Inserte la descripción de la imagen aquí

Inserte la descripción de la imagen aquí


  • Pasos para crear un objeto

    1. Determinar si la clase correspondiente al objeto está cargada, vinculada, inicializada

      Cuando la máquina virtual encuentra una nueva instrucción, primero verifica si el parámetro de esta instrucción puede ubicar una referencia de símbolo de una clase en el grupo constante de Metaspace y verifica si la clase representada por esta referencia de símbolo se ha cargado, analizado y inicializado. (Es decir, para determinar si existe la metainformación). De lo contrario, en el modo de delegación parental, use el cargador de clases actual para encontrar el archivo .class correspondiente con ClassLoader + nombre de paquete + nombre de clase Key. Si no se encuentra el archivo, se lanzará una ClassNotFoundException, si se encuentra, se cargará la clase y se generará el objeto Classs correspondiente.

    2. Asignar memoria para el objeto

      Primero calcule el espacio ocupado por el objeto y luego asigne un bloque de memoria en el montón para el nuevo objeto. Si la variable miembro de instancia es una variable de referencia, simplemente asigne el espacio de la variable de referencia, que tiene un tamaño de 4 bytes.

      • Si la memoria es regular, use puntero colisión

        Si la memoria es regular, la máquina virtual usará Bump The Pointer para asignar memoria para el objeto. Significa que toda la memoria utilizada está en un lado y la memoria libre está en el otro lado. Hay un puntero en el medio como indicador del punto de demarcación. Asignar memoria es simplemente mover el puntero hacia el lado libre por un distancia igual al tamaño del objeto. Si el recolector de basura elige Serial y ParNew según el algoritmo de compresión de marcas, la máquina virtual usa este método de asignación. Generalmente, cuando se usa un colector con un proceso compacto, se usa la colisión de puntero.

      • Si la memoria no es regular, la máquina virtual necesita mantener una lista y usar la lista libre para asignar

        Si la memoria no es regular, la memoria utilizada y la memoria no utilizada se intercalan entre sí, entonces la máquina virtual utilizará el método de lista libre para asignar memoria para el objeto. Significa que la máquina virtual mantiene una lista para registrar qué bloques de memoria están disponibles. Al redistribuir, busque un espacio lo suficientemente grande en la lista para dividir la instancia del objeto y actualizar el contenido de la lista. Este método de asignación se denomina "Lista libre".

        Nota : La elección del método de asignación está determinada por si el montón de Java es regular y si el montón de Java es regular está determinado por si el recolector de basura utilizado tiene una función de compresión.

    3. Manejo de problemas de seguridad de simultaneidad

      Al asignar espacio en la memoria, otro problema es garantizar la seguridad de los subprocesos de nuevos objetos en el tiempo: la creación de objetos es una operación muy frecuente y la máquina virtual debe resolver el problema de la seguridad de la concurrencia. La máquina virtual utiliza dos métodos para resolver el problema de seguridad de la concurrencia:

      • Reintento de falla CAS (Compare And Swap), bloqueo de área: para garantizar la atomicidad de la operación de actualización del puntero;
      • La acción correcta de TLAB de acuerdo con la asignación de memoria se divide entre diferentes subprocesos de espacio que cada subproceso una pequeña pieza de memoria de pila preasignada en Java, llamado búfer de asignación local de subprocesos (TLAB, búfer de asignación local de subprocesos) , una máquina virtual Ya sea Usar TLAB o no se puede configurar con el parámetro -XX: +/- UseTLAB.
    4. Inicializar el espacio asignado

      Una vez finalizada la asignación de memoria, el espacio de memoria asignado por la máquina virtual se inicializa a un valor de cero (excluyendo el encabezado del objeto). Este paso asegura que los campos de instancia del objeto se puedan usar directamente en el código Java sin asignar valores iniciales, y que el programa pueda acceder a los valores cero correspondientes a los tipos de datos de estos campos.

    5. Establecer el encabezado del objeto del objeto

      Almacene la clase del objeto (es decir, la información de metadatos de la clase), el HashCode del objeto, la información de GC del objeto, la información de bloqueo y otros datos en el encabezado del objeto del objeto. La configuración específica de este proceso depende de la implementación de JVM.

    6. Ejecute el método init para inicializar

      Desde el punto de vista de un programa Java, la inicialización solo ha comenzado oficialmente. Inicialice las variables miembro, ejecute el bloque de código instanciado, llame al método de construcción de la clase y asigne la primera dirección del objeto en el montón a la variable de referencia.

      Por lo tanto, en términos generales (determinado por si el código de bytes va seguido de la instrucción especial invocada), el método de ejecución seguirá después de la nueva instrucción.El objeto se inicializa según los deseos del programador, de modo que se crea por completo un objeto realmente utilizable.

2 El diseño de la memoria del objeto

  • ¿Qué contenido contiene el objeto creado en el montón?

    Inserte la descripción de la imagen aquí

    No todos los objetos guardan los punteros de tipo

  • ejemplo

    /**
     * 测试对象实例化的过程
     *  ① 加载类元信息 - ② 为对象分配内存 - ③ 处理并发问题  - ④ 属性的默认初始化(零值初始化)
     *  - ⑤ 设置对象头的信息 - ⑥ 属性的显式初始化、代码块中初始化、构造器中初始化
     *
     *
     *  给对象的属性赋值的操作:
     *  ① 属性的默认初始化 - ② 显式初始化 / ③ 代码块中初始化 - ④ 构造器中初始化
     */
    
    public class Customer{
          
          
        int id = 1001;  // ② 显式初始化
        String name;
        Account acct;
    
        {
          
          
            name = "匿名客户";  // ③ 代码块中初始化
        }
        public Customer(){
          
          
            acct = new Account();  // ④ 构造器中初始化
        }
    
    }
    class Account{
          
          
    
    }
    
    public class CustomerTest {
          
          
        public static void main(String[] args) {
          
          
            Customer cust = new Customer();
        }
    }
    

    Inserte la descripción de la imagen aquí

3 Acceda a la ubicación del objeto

Inserte la descripción de la imagen aquí

  • ¿Cómo accede la JVM a sus instancias de objetos internos a través de las referencias de objetos en el marco de pila?

    • Acceso por referencia en la pila

    Inserte la descripción de la imagen aquí

  • Dos formas de acceso a objetos

    • Manejar el acceso

      Inserte la descripción de la imagen aquí

      • Ventajas: solo es necesario cambiar la dirección en el grupo de controles después de GC
      • Desventajas: baja eficiencia de acceso, el acceso a datos de instancia y metadatos requiere una transferencia
    • Puntero directo (adoptado por Hotspot)

      Inserte la descripción de la imagen aquí

      Ventajas: alta eficiencia de acceso, acceso a los datos de la instancia en un solo paso

      Desventajas: después de GC, es necesario cambiar la dirección de referencia en la tabla de variables locales en la pila de la máquina virtual

Supongo que te gusta

Origin blog.csdn.net/weixin_42638946/article/details/113646905
Recomendado
Clasificación