El grupo de constantes de clase puede entenderse como un almacén de recursos en el archivo de clase. Además del archivo de clase que contiene las versiones de la clase, los campos, los métodos y la información de descripción de la interfaz, hay una información de grupo constante (tabla de grupo constante), para almacenar una variedad de literales generados por el compilador (el literal) y referencias simbólicas ( Referencias simbólicas).
La estructura hexadecimal de un archivo de clase es la siguiente: el
significado correspondiente es el siguiente, puede consultar el documento oficial de Oracle para obtener más detalles.
Por supuesto, generalmente no analizamos este archivo de código de bytes hexadecimal manualmente, generalmente podemos generarlo a través del comando javap Archivo de instrucciones de
código de bytes JVM más legible: javap -v Math.class
Classfile /E:/open/demo/target/classes/com/example/demo/test/opencv/Math.class
Last modified 2020-9-20; size 619 bytes
MD5 checksum f70c67abc97af9f0978a807380fcb072
Compiled from "Math.java"
public class com.example.demo.test.opencv.Math
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #5.#26 // java/lang/Object."<init>":()V
#2 = Class #27 // com/example/demo/test/opencv/Math
#3 = Methodref #2.#26 // com/example/demo/test/opencv/Math."<init>":()V
#4 = Methodref #2.#28 // com/example/demo/test/opencv/Math.compute:()I
#5 = Class #29 // java/lang/Object
#6 = Utf8 <init>
#7 = Utf8 ()V
#8 = Utf8 Code
#9 = Utf8 LineNumberTable
#10 = Utf8 LocalVariableTable
#11 = Utf8 this
#12 = Utf8 Lcom/example/demo/test/opencv/Math;
#13 = Utf8 compute
#14 = Utf8 ()I
#15 = Utf8 a
#16 = Utf8 I
#17 = Utf8 b
#18 = Utf8 c
#19 = Utf8 main
#20 = Utf8 ([Ljava/lang/String;)V
#21 = Utf8 args
#22 = Utf8 [Ljava/lang/String;
#23 = Utf8 math
#24 = Utf8 SourceFile
#25 = Utf8 Math.java
#26 = NameAndType #6:#7 // "<init>":()V
#27 = Utf8 com/example/demo/test/opencv/Math
#28 = NameAndType #13:#14 // compute:()I
#29 = Utf8 java/lang/Object
{
public com.example.demo.test.opencv.Math();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/demo/test/opencv/Math;
public int compute();
descriptor: ()I
flags: ACC_PUBLIC
Code:
stack=2, locals=4, args_size=1
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: bipush 10
9: imul
10: istore_3
11: iload_3
12: ireturn
LineNumberTable:
line 6: 0
line 7: 2
line 8: 4
line 9: 11
LocalVariableTable:
Start Length Slot Name Signature
0 13 0 this Lcom/example/demo/test/opencv/Math;
2 11 1 a I
4 9 2 b I
11 2 3 c I
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=1
0: new #2 // class com/example/demo/test/opencv/Math
3: dup
4: invokespecial #3 // Method "<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method compute:()I
12: istore_2
13: return
LineNumberTable:
line 14: 0
line 15: 8
line 16: 13
LocalVariableTable:
Start Length Slot Name Signature
0 14 0 args [Ljava/lang/String;
8 6 1 math Lcom/example/demo/test/opencv/Math;
13 1 2 compute I
}
SourceFile: "Math.java"
Hay principalmente dos tipos de constantes almacenadas en el grupo de constantes: referencias literales y simbólicas .
Literales
literales se refiere a una cadena de letras, números o constantes numéricas similares el
valor literal solo puede aparecer a la derecha, llamado valor correcto es el valor a la derecha del signo igual, como por ejemplo: int a = 1 aquí es un valor a la izquierda 1 es el valor correcto. En este ejemplo, 1 es la cantidad literal.
int a = 1;
int b = 2;
int c = "abcdefg";
Referencia de símbolo La referencia de
símbolo es un concepto en el principio de compilación, que es relativo a la referencia directa. Incluye principalmente los siguientes tres tipos de constantes:
- Nombres de clases e interfaces completamente calificados
- Nombre de campo y descriptor
La a y la b encima del nombre del método y el descriptor son los nombres de campo, que es una referencia simbólica, y Lcom / example / demo / test / opencv / Math en el grupo constante de la clase Math es el nombre completo de la clase, main y compute Es el nombre del método, () es un descriptor en formato UTF8, estos son referencias a símbolos.
Estos grupos de constantes ahora son información estática. Solo cuando se cargan en la memoria en tiempo de ejecución, estos símbolos tienen la información de dirección de memoria correspondiente. Una vez que estos grupos de constantes se cargan en la memoria, se convierten en grupos de constantes de tiempo de ejecución. Las referencias de símbolos correspondientes están en Cuando el programa se carga o se ejecuta, se convertirá en una referencia directa al código cargado en el área de memoria, que es lo que llamamos enlace dinámico. Por ejemplo, la referencia simbólica de compute () se convertirá en la dirección de memoria del código específico del método compute () en tiempo de ejecución, y la referencia directa se convierte principalmente a través del puntero de tipo en el encabezado del objeto.
Jdk1.6 y antes: hay una generación permanente, y la reserva constante está en el área de método.
Jdk1.7: Hay una generación permanente, pero ha sido gradualmente "de-permanente". La reserva constante está en la pila
Jdk1.8 y posteriores: no hay generación permanente, y la reserva constante está en el yuan espacio
Grupo constante de cadenas
Ideas de diseño de String Constant Pool
- La asignación de cadenas, como otras asignaciones de objetos, consume un alto costo de tiempo y espacio.Como el tipo de datos más básico, se crea una gran cantidad de cadenas frecuentes, lo que afecta en gran medida el rendimiento del programa.
- Para mejorar el rendimiento y reducir la sobrecarga de memoria, JVM ha realizado algunas optimizaciones al crear instancias de constantes de cadena
Cree un grupo de constantes de cadena para una cadena, similar a un área de búfer. Al crear una constante de cadena, primero insista en si la cadena
existe en el grupo de constantes de cadena, devuelva la instancia de referencia, si no existe, cree una instancia de la cadena y póngala En la piscina
Ejemplo de código, algunas operaciones de variable local de cadena
String str1 = "abc";
String str2 = "abc";
String str3 = "abc";
String str4 = new String("abc");
String str5 = new String("abc");
String str5 = new String("abc");
Puntos y áreas seguras
Punto seguro
Los puntos de seguridad se refieren a ubicaciones específicas en el código. Cuando el subproceso se ejecuta en estas ubicaciones, se determina su estado, de modo que la JVM puede realizar de forma segura algunas operaciones, como GC, etc., por lo que GC no se activa inmediatamente cuando quiere hacerlo , Es necesario esperar a que todos los subprocesos se ejecuten en un punto seguro antes de activarse. Las ubicaciones de estos puntos de seguridad específicos son principalmente las siguientes:
- Antes de que vuelva el método
- Después de llamar a un método
- Donde se lanzó la excepción
- Fin del ciclo
Area segura
Safe Point se establece para el subproceso que se está ejecutando.
Si un subproceso está en estado de suspensión o interrupción, no puede responder a la solicitud de interrupción de la JVM y luego ejecutarse al punto seguro. Por lo tanto, la JVM introdujo Safe Region.
Región segura significa que en un fragmento de código, la relación de referencia no cambiará . Es seguro iniciar GC en cualquier lugar de esta área. Cuando el hilo ingresa a la Región Segura, primero marca que ha entrado en la Región Segura, y cuando se despierta para salir de la Región Segura, primero verifica si puede salir. Si el GC se completa, el hilo puede salir, de lo contrario debe esperar hasta que reciba el seguro La señal para irse.