En general, se cree que los objetos nuevos están asignados en el montón, pero esto no es completamente correcto. A través del análisis del proceso de asignación de objetos Java, encontramos que, además de ser asignado en el montón, los objetos también pueden asignar espacio en la pila o TLAB. La base técnica para asignar objetos en la pila es el análisis de escape y el reemplazo escalar. Este artículo presenta principalmente el análisis de escape.
Definición de análisis de escape
El análisis de escape es un algoritmo de análisis de flujo de datos global multifuncional que puede reducir efectivamente la presión de carga sincrónica y la presión de asignación de montón de memoria en los programas Java.
A través del análisis de escape, el compilador de punto de acceso Java puede analizar el alcance de uso de la referencia de un nuevo objeto y determinar si asigna el objeto al montón.
Java admite y permite opciones de análisis de escape en Java SE 6U23 y versiones posteriores. El compilador JIT del punto de acceso de Java puede realizar un análisis de escape del código cuando el método se sobrecarga o se carga dinámicamente.
El comportamiento básico del análisis de escape es analizar el alcance dinámico de un objeto: cuando un objeto se define en un método, puede referenciarlo por un método externo.
Escape del método: por ejemplo, pase como un parámetro de llamada a otros métodos.
Escape de subprocesos: se puede acceder mediante hilos externos, como asignar valores a variables de clase o variables de instancia a las que se puede acceder en otros hilos.
Base teórica del análisis de escape
El análisis de escape se realiza en base al algoritmo descrito por Jong-Deok Choi, Manish Gupta, Mauricio Seffano, Vugramam C. Sreedhar, Sam Midkiff y otros en el artículo "Análisis de escape para Java".
Este algoritmo introduce un gráfico conectado y utiliza el gráfico conectado para construir la relación accesible entre la referencia de objeto y objeto, y sobre la base de esto, se propone un método de análisis de flujo de datos combinado. Dado que el algoritmo es dependiente del contexto y sensible a la corriente, y simula relaciones anidadas en cualquier nivel del objeto, la precisión del análisis es alta, pero el tiempo de ejecución y el consumo de memoria son relativamente grandes.
La mayoría de las implementaciones del análisis de escape se basan en la premisa del "mundo cerrado": todos los métodos posibles que se ejecutan se conocen antes del análisis de escape, y la operación real del programa no cambiará la relación de llamadas entre ellos. Pero cuando se ejecuta un programa Java real, tales supuestos no son verdaderos. Muchas características de los programas de Java, como la carga de clase dinámica, la llamada de las funciones locales y las llamadas del programa, romperán la llamada convención "cerrada del mundo".
Operaciones de procesamiento después del análisis de escape
Después del análisis de escape, se pueden obtener tres posibles estados de escape del objeto:
Globalcape: es decir, la referencia de un objeto escapa de un método o hilo. Por ejemplo, la referencia de un objeto se copia a una variable de clase, o se almacena en un objeto que ha escapado, o la referencia del objeto se devuelve al método de llamada como el valor de retorno del método.
Argascape (escape de nivel de parámetro): es decir, la aplicación del objeto pasada a un método durante el proceso de llamadas de método. Este estado se puede determinar analizando el código binario del método que se está sintonizar.
Nocape: un objeto que puede ser reemplazado por escalares. El objeto no puede asignarse en un montón tradicional.
El compilador puede usar los resultados del análisis de escape para optimizar el programa:
El objeto de asignación del montón se convierte en un objeto de asignación de pila: un objeto en un método, y la referencia del objeto no escapa, por lo que este método puede asignarse en la memoria de la pila y es muy común a la memoria de montón.
Elimine la sincronización: el costo de la sincronización de hilos es bastante alto, y las consecuencias de la sincronización son la concurrencia y el rendimiento reducidos. El análisis de escape puede determinar si siempre se accede a un objeto un solo hilo. Si solo se accede por un solo hilo, entonces la operación de sincronización del objeto se puede convertir en una operación sin protección de sincronización, lo que puede mejorar en gran medida el grado de concurrencia y rendimiento.
Sustitución del vector: método de análisis de escape Si encuentra que la estructura de almacenamiento de memoria del objeto no necesita llevarse a cabo continuamente, puede guardar piezas e incluso todo el objeto en los registros de la CPU, lo que puede mejorar en gran medida la velocidad de acceso.