"Comprensión profunda de la máquina virtual Java" notas de lectura Capítulo 8 Motor de ejecución de código de bytes de la máquina virtual

Haga clic para ver la colección de lectura y peinado "Comprensión detallada de la máquina virtual Java"

Estructura del marco de pila en tiempo de ejecución

La máquina virtual java toma métodos como la unidad de ejecución más básica. El marco de pila es la estructura de datos detrás de la llamada al método y la ejecución del método que soporta la máquina virtual. También es el área de datos en tiempo de ejecución y el elemento de pila de la pila de la máquina virtual. El marco de pila almacena la tabla de variables locales del método, la pila de operandos, la dirección de retorno del método de enlace dinámico y el contador de PC y otra información.

Tabla de variables locales

La tabla de variables locales es un espacio de almacenamiento para un conjunto de valores de variables, que se utiliza para almacenar los parámetros del método y las variables locales definidas dentro del método. Cuando el programa java se compila en un archivo de clase, la capacidad máxima de la tabla de variables locales que debe asignarse al método se determina en el elemento de datos max_locals del atributo Code del método.
La capacidad de la lista enlazada local se basa en la ranura variable, a excepción de double y Long, ambas ocupan una ranura (ocupan dos ranuras). Las ranuras se pueden reutilizar.

Pila de operandos

La profundidad de la pila de operandos también se determina en tiempo de compilación. El operando debe colocarse en la pila de operandos antes de operar en el operando. Por ejemplo, al realizar operaciones aritméticas, primero inserte el operando en la parte superior de la pila de operandos y luego llame a la instrucción aritmética para continuar.

Enlace dinámico

Cada marco de pila contiene una referencia al método al que pertenece el marco de pila en el grupo de constantes de tiempo de ejecución. Esta referencia se mantiene para admitir la conexión dinámica durante la invocación del método. Hay una gran cantidad de referencias de símbolos en el grupo constante del archivo Class. La instrucción de llamada al método en el código de bytes toma la referencia de símbolo que apunta al método en el grupo constante como parámetro. Algunas de estas referencias de símbolos se convertirán en referencias directas durante la etapa de carga de la clase o la primera vez que se utilicen. Esta conversión se denomina resolución estática. La otra parte se convierte en una referencia directa cada vez que se ejecuta, y esta parte se denomina vinculación dinámica.

Dirección de devolución del método

Cuando un método comienza a ejecutarse, hay dos formas de iniciar este método, la primera es la declaración de retorno. El otro es lanzar una excepción. De cualquier manera, después de que el método salga, debe regresar al lugar donde se llamó al método original. Si sale normalmente, el contador de PC probablemente se almacena en el marco de la pila y este contador de programa se puede utilizar como la dirección de retorno del método.
Si se trata de una salida anormal, la dirección de retorno debe determinarse de acuerdo con la tabla de excepciones.

información extra

La máquina virtual puede agregar información que no se describe en la especificación al marco de la pila. Por ejemplo, información relacionada con la recopilación de depuración y rendimiento. Esta parte de la información depende de la implementación de la máquina virtual específica.

Llamada de método

La invocación del método no significa que se ejecuta el código del método, sino que determina la versión del método que se llama.

Analizando

Si el método tiene una versión de llamada determinable antes de que se ejecute el programa, en la fase de análisis de la carga de clases, la referencia simbólica del método se convertirá directamente en una referencia directa. La invocación de este tipo de método se denomina resolución.
En Java, los métodos que cumplen con los requisitos del compilador para ser inmutables en tiempo de ejecución incluyen métodos estáticos, métodos finales, métodos privados, métodos principales y métodos de constructor. Estos métodos se denominan métodos no virtuales y los otros métodos se denominan métodos virtuales.
La llamada de análisis debe ser un proceso estático, que se puede determinar completamente durante la compilación.En la etapa de análisis de carga de clases, todas las referencias de símbolos del diseño se convertirán en referencias directas explícitas.

Envío

El proceso de llamada de despacho revelará algunas de las manifestaciones más básicas del polimorfismo, como la reescritura y la sobrecarga.

Despacho estático


public class Main1 {
    
    
    static class Human {
    
    
    }
    static class Father extends Human{
    
    
    }
    static class Son extends Human{
    
    
    }
    public void who(Human human){
    
    
        System.out.println("i am human");
    }
    public void who(Father father){
    
    
        System.out.println("i am father");
    }
    public void who(Son son){
    
    
        System.out.println("i am son");
    }

    public static void main(String[] args) {
    
    
        Main1 main1 = new Main1();
        Human father = new Father();
        Human son = new Son();
        main1.who(son);
        main1.who(father);
    }
}

Inserte la descripción de la imagen aquí
Tomemos como ejemplo la declaración
Padre humano = nuevo Padre (); Humano se llama tipo estático o tipo de apariencia, y Padre se llama tipo real o tipo en tiempo de ejecución. Tanto el tipo estático como el tipo real pueden cambiar en el programa. , La diferencia es que el tipo estático cambia solo cuando se usa, y el tipo estático de la variable en sí no se adaptará. Y el tipo estático final se conoce en tiempo de compilación. El resultado del cambio de tipo real solo se puede determinar durante el tiempo de ejecución. Cuando se sobrecarga, está determinado por el tipo estático del parámetro en lugar del tipo real. Todas las acciones de envío que se basan en tipos estáticos para determinar la versión de ejecución de un método se denominan envío estático. El escenario de aplicación más clásico de distribución estática es la sobrecarga. El envío estático se produce durante la fase de compilación.





Despacho dinámico

El envío dinámico y la reescritura están estrechamente relacionados. Es el método que tiene polimorfismo, pero el campo no tiene polimorfismo.

public class Main1 {
    
    
    static class Father {
    
    
        int age;
        public Father(){
    
    
            age = 40;
            show();
        }
        public void show(){
    
    
            System.out.println("father is "+age+" age");
        }
    }
    static class Son extends Father{
    
    
        int age;
        public Son(){
    
    
            age = 10;
            show();
        }
        public void show(){
    
    
            System.out.println("son is "+age+" age");
        }
    }

    public static void main(String[] args) {
    
    
        Father son = new Son();
        son.show();
    }
}

Inserte la descripción de la imagen aquí
El despacho dinámico debe determinar primero el tipo real del parámetro y luego encontrar la versión del método que se ejecutará en función del tipo real.

Interpretación y ejecución

Inserte la descripción de la imagen aquí
La máquina virtual hotsport se basa en la interpretación y ejecución de la pila.

Supongo que te gusta

Origin blog.csdn.net/qq_30033509/article/details/115031487
Recomendado
Clasificación