Elaboración de valor y análisis del proceso de carga de clases (9)

Fase de preparación

La etapa de preparación es la etapa de asignación formal de memoria para las variables definidas en la clase (variables estáticas, variables modificadas por estáticas) y establecer el valor inicial de las variables de la clase , excluidas las variables de instancia.

public static int value = 123;
此时只会将value赋值为初始值0.真正赋值为123是在类构造器 < clinit>() 方法中。


public static final int value = 123;
准备阶段就会将value赋值为123

Analizando

La fase de análisis es un proceso en el que la máquina virtual Java reemplaza las referencias de símbolos en el grupo constante con referencias directas .

Referencia simbólica

La referencia de símbolo utiliza un conjunto de símbolos para describir el destino referenciado. Los símbolos pueden ser literales en cualquier forma. El destino de referencia no está necesariamente dentro de la memoria de la máquina virtual. La forma literal de la referencia de símbolo se especifica claramente en el archivo de clase.

Cita directa

Una referencia directa es un puntero que puede apuntar directamente al objetivo, un desplazamiento relativo o un identificador que se puede ubicar indirectamente en el objetivo, y el objetivo de referencia debe existir en la máquina virtual.

La acción de análisis se dirige principalmente a clases o interfaces, campos, métodos de clase y métodos de interfaz. Los 7 tipos de referencia simbólica , tipo de método, identificador de método y calificador de punto de llamada

Resolución de clase o interfaz

Suponiendo que la clase actual es D, si desea resolver una referencia de símbolo no resuelta N en una referencia directa a una clase o interfaz C, todo el proceso de resolución de la máquina virtual requiere tres pasos:

  1. Si C no es un tipo de matriz, la máquina virtual pasa el nombre completo que representa a N al cargador de clases de D para cargar C. Durante el proceso de carga, se pueden activar otras acciones de carga.
  2. Si C es un tipo de matriz y el tipo de elemento de carga de matriz es un objeto, cargue el tipo de elemento de matriz.
  3. Si no hay excepciones en los dos pasos anteriores, entonces C se ha convertido en una clase o interfaz válida en la máquina virtual, pero se requiere la verificación del símbolo antes de que se complete el análisis para confirmar si D tiene acceso a C. Si no tiene permiso, se lanzará una excepción java.lang.IllegalAccessError.

Después de que JDK9 introduzca la modularidad, verifique los derechos de acceso entre los módulos.
Si D tiene derechos de acceso para C, significa que al menos uno de los siguientes tres elementos es verdadero:

  1. La clase C a la que se accede es pública y está en el mismo módulo que la clase D a la que se accede.
  2. La clase C accedida es pública y no se encuentra en el mismo módulo que la clase D accedida, pero el módulo de la clase C accedida permite acceder al módulo de la clase D accedida.
  3. La clase visitada C no es pública, pero está en el mismo paquete que la clase visitada D.

Resolución de campo

Para resolver una referencia de símbolo de campo no resuelta, la referencia de símbolo CONSTANT_Class_info en el elemento class_index en la tabla de campo se resolverá primero.
Una vez completado el análisis, se requiere la búsqueda de campo subsiguiente para esta clase o interfaz C:

  1. Si el propio C contiene un campo cuyo nombre simple y descriptor de campo coinciden con el objetivo, se devuelve una referencia directa a este campo y la búsqueda finaliza.
  2. De lo contrario, si la interfaz está implementada en C, se buscará en cada interfaz de forma recursiva de acuerdo con la relación de herencia. Si la interfaz contiene un campo cuyo nombre simple y descriptor de campo coinciden con el objetivo, se devolverá una referencia directa a este campo y la búsqueda finalizará. .
  3. De lo contrario, si C no es java.lang.Object, la clase principal se buscará de abajo hacia arriba de acuerdo con la relación recursiva. Si la clase principal contiene un campo cuyo nombre simple y descriptor de campo coinciden con el objetivo, devuelve el valor de este campo. Cotiza directamente y finaliza la búsqueda.
  4. De lo contrario, la búsqueda falla y se lanza una excepción java.lang.NoSuchFieldError.
    Si el resultado se vuelve a poner como referencia, se autenticará.

Análisis de métodos

Primero analice la referencia simbólica de la clase o interfaz a la que pertenece el método de índice en el elemento class_index de la tabla de métodos. Si el análisis es exitoso, use C para representar esta clase, y luego la máquina virtual buscará de acuerdo con los siguientes pasos:

  1. Dado que los tipos de constantes a los que hace referencia el método de clase y el símbolo del método de interfaz en el formato de archivo de clase están separados, si se encuentra que C es una interfaz, se lanzará la excepción java.lang.IncompatibleClassChangeError.
  2. Busque el método en C que contenga el nombre simple y el descriptor de campo que coincida con el objetivo, si hay una referencia directa a este método, la búsqueda finaliza.
  3. De lo contrario, busque de forma recursiva métodos que contengan nombres simples y descriptores de campo que coincidan con el objetivo en la clase principal de la clase C. Si hay métodos, devuelva una referencia directa a este método y la búsqueda finaliza.
  4. De lo contrario, busque de forma recursiva en la lista de interfaces de implementación de la clase C y sus interfaces de clase padre si hay métodos que contienen nombres simples y descriptores de campo que coinciden con el objetivo. Si es así, significa que C es una clase abstracta, que es una búsqueda La excepción java.lang.AbstractMethodError se lanza al final.
  5. De lo contrario, la búsqueda del método falla y se lanza java.lang.NoSuchMethodError.
    Finalmente, si la búsqueda tiene éxito y se devuelve una referencia directa, se autentica la autorización de este método.

Análisis del método de interfaz

Primero analice la referencia simbólica de la clase o interfaz a la que pertenece el método de índice en el elemento class_index publicado por la parte de la interfaz. Si el análisis es exitoso, use C para representar esta interfaz, y luego la máquina virtual buscará de acuerdo con los siguientes pasos:

  1. Al contrario de la resolución del método, se lanza una excepción si es una clase.
  2. De lo contrario, busque el método que contiene el nombre simple y el descriptor de campo que coincida con el objetivo en la interfaz C, si hay una referencia directa a este método, y la búsqueda finaliza.
  3. De lo contrario, busque de forma recursiva en su interfaz principal hasta que se encuentre la clase java.lang.Object, y vea si hay un método con un nombre simple y un descriptor de campo que coincida con el objetivo, si hay una referencia directa a este método, la búsqueda termina .
  4. Dado que se permite la herencia múltiple de interfaces Java, si hay métodos con nombres simples y descriptores de campo que coinciden con el objetivo en diferentes clases principales, uno de ellos se volverá a colocar.
  5. De lo contrario, la búsqueda falla.

Supongo que te gusta

Origin blog.csdn.net/weixin_43663421/article/details/109289643
Recomendado
Clasificación