Antes de comenzar el texto principal de este artículo, echemos un vistazo al siguiente código:
El papel de IntegerCache de la clase Integer en Java
Nombre del paquete: java.lang
Nombre del archivo: Integer.java
Nombre del método: IntegerCache
El código del método es el siguiente:
Clase estática privada IntegerCache {static final int high; Cache entero final estático []; static {final int low = -128; // El alto valor puede ser configurado por la propiedad int h = 127; if (integerCacheHighPropvalue! = null) {// use long.Decode aquí para evitar invocar métodos que // requieren la memoria caché de autoboxing de Integer para inicializarse int i = long.Decode (IntegerCacheHighPropvalue) .intvalue (); i = math.max (i, 127); // El tamaño máximo de la matriz es integer.max_value h = math.min (i, integer.max_value - -low); } high = h; caché = nuevo entero [(alto - bajo) + 1]; int j = bajo; para (int k = 0; k <cache.length; k ++) caché [k] = nuevo entero (j ++); } private integerCache () {}}Vemos en el código que bajo es -128 y alto es 127. De esta manera, en la programación de Java, si desea usar un objeto en el intervalo -128-127, usará directamente el objeto en este caché.
Lo anterior es una breve introducción para ayudar a todos a comprender IntegerCache. El siguiente es el texto principal de este artículo:
introducción
Hace 5 años, publiqué una publicación sobre húngaro sobre cómo cambiar IntegerCache en JDK. Este enfoque es en realidad profundizar en el tiempo de ejecución de Java y en realidad no se usa en escenarios. Cuando desarrolla este código de investigación, puede comprender mejor cómo funciona la reflexión y cómo la clase entera lo implementa.
La clase Integer tiene un integuercache con nombre privado, que contiene objetos enteros con valores que van de -127 a 128.
Cuando el código debe encerrarse desde el tipo int en un objeto entero, y el valor está dentro de este rango, el tiempo de ejecución de Java usará este caché en lugar de crear un nuevo objeto entero. Esto es principalmente para consideraciones de optimización del rendimiento. Debemos tener en cuenta que muchos valores INT a menudo están dentro de este rango en el programa (como el índice de subíndice de una matriz).
El efecto secundario de esto es que, muchas veces, cuando se usa el operador de signo igual para comparar dos objetos enteros, siempre que el valor esté dentro del rango, es válido. Esto es típico en las pruebas unitarias. En el modo Ejecutar, cuando el valor es mayor que 128, la ejecución del código fallará.
El uso de la reflexión para acceder a las clases de IntegerCache puede causar algunos efectos secundarios extraños, tenga en cuenta que esto afecta a todo el JVM. Si un servlet redefine un valor de caché de enteros pequeños, todos los demás servlets que se ejecutan bajo el mismo Tomcat encuentran el mismo problema.
Hay otros artículos arriba en Lukas Eder y SitePoint.
Ahora que estoy jugando con los primeros lanzamientos de Java 9, todo lo que siempre he tenido que hacer en mi mente es experimentar con nuevas versiones de Java. Antes de comenzar, echemos un vistazo a cómo hacerlo en Java 8.
En el artículo de Lukas, publiqué su código de muestra aquí:
import java.lang.reflect.field; import java.util.random; public class entropy {public static void main (string [] args) arroja excepción {// extraer el enterograque a través de la clase de reflexión <<? > clazz = class.forname ("java.lang.integer $ IntegerCache"); Campo campo = clazz.getDeclaredfield ("caché"); campo.setAccessible (verdadero); Entero [] cache = (entero []) campo.get (clazz); // Reescribe el caché entero para (int i = 0; i <cache.length; i ++) {cache [i] = new Integer (new Random (). NextInt (Cache.Length)); } // probar aleatoriedad para (int i = 0; i <10; i ++) {system.out.println ((integer) i); }}}Este código accede a IntegerCache a través de la reflexión y luego usa valores aleatorios para llenar el caché (¡travieso!).
Intentamos ejecutar el mismo código en Java 9, no esperamos divertirse. Cuando alguien intente violarlo, encontrará que Java 9 es más restrictivo.
Excepción en el hilo "principal" java.lang.reflect.inaccessibleObjectException: no se puede hacer que el campo está estático final java.lang.integer [] java.lang.integer $ integercache.cache accesible: el módulo java.base no "abre java.lang" a module nocado @1bc6a36e3e3e.
El programa lanza una excepción, que no ocurrirá en Java 8. Es equivalente a decir que los objetos no están basados en modelos. Debido al módulo Java.Base, esta es una parte integral del JDK. Se importa automáticamente cuando se inicia cada programa de Java, y no se permite que se abran módulos sin nombre. Esta excepción se lanza cuando intentamos establecer la propiedad accesible para el campo.
Los objetos a los que podemos acceder fácilmente en Java 8 ahora no son accesibles en Java 9 porque el nuevo sistema de módulos protege esto. El código solo puede acceder a campos, métodos y otra información a la que se puede acceder mediante reflexión, solo si la clase está en el mismo módulo, o el módulo tiene un paquete abierto para el acceso a la reflexión. Esto se puede implementar a través del archivo de definición del módulo del módulo-Info.java:
módulo mymodule {exports com.javax0.module.demo; abre com.javax0.module.demo;} Este módulo java.base no es necesario para abrirlo por sí solo para el acceso a la reflexión, especialmente para módulos sin nombre. Si creamos un módulo y lo nombraremos, el mensaje de error contendrá el nombre del módulo.
¿Podemos abrir módulos en el programa? El módulo java.lang.reflect.Module tiene un método addopens que se puede hacer.
¿Es factible?
La mala noticia para los desarrolladores es: no es factible. Solo puede abrir un paquete en un módulo en otro módulo, y el paquete se ha abierto en ese módulo llamando a este método. Este método solo puede permitir que los módulos se pasen a otros derechos del módulo, siempre que el otro módulo haya abierto el mismo paquete de alguna manera y no pueda abrir paquetes sin abrir (nota del traductor: es difícil de entender, ¿no?).
Pero al mismo tiempo, la buena noticia es: Java 9 no es tan fácil de descifrar como Java 8. Al menos esta vulnerabilidad está cerrada. Parece que Java está comenzando a desarrollarse hacia un nivel profesional, no solo un juguete (nota del traductor: ¿Quién dijo que Java es un juguete?). En el futuro cercano, puede migrar proyectos en idiomas RPG y Cobol a Java muy en serio. (Lo siento, estaba bromeando)
Resumir
Lo anterior es todo el contenido de este artículo. Espero que el contenido de este artículo tenga cierto valor de referencia para el estudio o el trabajo de todos. Si tiene alguna pregunta, puede dejar un mensaje para comunicarse. Gracias por su apoyo a Wulin.com.
Este artículo se traduce de: https://dzone.com/articles/hacking-the-integercache-in-java-9