Bevor Sie den Haupttext dieses Artikels beginnen, werfen wir einen Blick auf den folgenden Code:
Die Rolle von Integercache der Ganzzahlklasse in Java
Paketname: java.lang
Dateiname: Integer.java
Methodenname: IntegerCache
Der Code der Methode lautet wie folgt:
private statische Klasse IntegerCache {statische endgültige int hoch; statischer endgültiger Ganzzahl -Cache []; static {endgültig int low = -128; // hoher Wert kann durch Eigenschaft int H = 127 konfiguriert werden; if (IntegerCacheHighPropValue! i = math.max (i, 127); // Maximale Arraygröße ist integer.max_value h = math.min (i, integer.max_value - -low); } High = H; Cache = New Integer [(hoch - niedrig) + 1]; int j = niedrig; für (int k = 0; k <cache.length; k ++) cache [k] = new Integer (j ++); } private IntegerCache () {}}Wir sehen in dem Code, dass niedrig -128 und hoch ist 127. Auf diese Weise verwenden Sie in der Java -Programmierung das Objekt in diesem Cache direkt.
Das obige ist eine kurze Einführung, um jedem zu helfen, Integercache zu verstehen. Das Folgende ist der Haupttext dieses Artikels:
Einführung
Vor 5 Jahren habe ich einen Beitrag über Ungarn über die Änderung von Integercache in JDK veröffentlicht. Dieser Ansatz besteht tatsächlich darin, tief in die Java -Laufzeit einzusteigen und wird in Szenarien nicht verwendet. Wenn Sie diesen Forschungscode entwickeln, können Sie besser verstehen, wie die Reflexion funktioniert und wie die Ganzzahlklasse ihn implementiert.
Die Integer -Klasse hat einen privaten verschachtelten namens IntegerCache, der Ganzzahlobjekte mit Werten von -127 bis 128 enthält.
Wenn der Code vom INT -Typ in ein Ganzzahlobjekt eingeschlossen sein muss und der Wert in diesem Bereich liegt, verwendet die Java -Laufzeit diesen Cache, anstatt ein neues Ganzzahl -Objekt zu erstellen. Dies gilt hauptsächlich für Überlegungen zur Leistungsoptimierung. Wir müssen bedenken, dass viele int -Werte häufig in diesem Bereich im Programm liegen (z. B. der Indexindex eines Arrays).
Der Nebeneffekt davon ist, dass bei Verwendung des gleichen Vorzeichenoperators zwei Ganzzahlobjekte, sofern der Wert innerhalb des Bereichs liegt, ein Vielfaches gültig ist, wenn er gültig ist. Dies ist typisch für Unit -Tests. Im Laufmodus schlägt die Codeausführung, wenn der Wert größer als 128 ist, fehl.
Beachten Sie, dass dies die gesamte JVM beeinflusst, wenn Sie Reflection zum Zugriff auf IntegerCache -Klassen zu einigen seltsamen Nebenwirkungen verursachen. Wenn ein Servlet einen kleinen Ganzzahl -Cache -Wert neu definiert, stoßen alle anderen Servlets, die unter demselben Tomcat laufen, dasselbe Problem.
Es gibt andere Artikel oben in Lukas Eder und SitePoint.
Jetzt, wo ich mit den frühen Veröffentlichungen von Java 9 spiele, musste ich immer in meinem Kopf immer nur mit neuen Java -Versionen experimentieren. Bevor wir anfangen, werfen wir einen Blick darauf, wie es in Java 8 geht.
In Lukas 'Artikel habe ich hier seinen Beispielcode gepostet:
importieren java.lang.reflect.field; import Java.util.random; öffentliche Klasse Entropie {public static void main (String [] args) löst eine Ausnahme aus {// den IntegerCache durch Reflexionsklasse << extrahieren? > clazz = class.forname ("java.lang.InEger $ Integercache"); Field field = clazz.getDeclaredfield ("Cache"); field.setAccessible (true); Integer [] Cache = (Integer []) field.get (Clazz); // Schreiben Sie den Integer -Cache für (int i = 0; i <cache.length; i ++) {cache [i] = new Integer (neu Random (). NextInt (Cache.Length)); } // Zufälligkeit für (int i = 0; i <10; i ++) {System.out.println ((Integer) i); }}}Dieser Code greift durch Reflexion auf IntegerCache zu und verwendet dann zufällige Werte, um den Cache zu füllen (frech!).
Wir versuchen, den gleichen Code in Java 9 auszuführen, erwarten Sie keinen Spaß. Wenn jemand versucht, es zu verletzen, wird es feststellen, dass Java 9 restriktiver ist.
Ausnahme in Thread "Main" java.lang.reflect.inaccessibleObjectexception: Field statische endgültige java.lang.Integer [] java.lang.Ineger $ Integercache.cache Accessible: Modul java.base nicht "öffnet Java.lang" to namned modul @1bc6a36e @to namnamed modul @1bc6a3e
Das Programm bringt eine Ausnahme aus, die in Java 8 nicht auftritt. Es ist gleichbedeutend mit der Aussage, dass Objekte nicht modellbasiert sind. Aufgrund des Java.Base -Moduls ist dies ein integraler Bestandteil des JDK. Es wird automatisch importiert, wenn jedes Java -Programm gestartet wird, und unbenannte Module dürfen nicht geöffnet werden. Diese Ausnahme wird ausgelöst, wenn wir versuchen, das Feld zugänglich zu machen.
Die Objekte, auf die wir in Java 8 leicht zugreifen können, sind in Java 9 jetzt nicht zugänglich, da das neue Modulsystem dies schützt. Der Code kann nur auf Felder, Methoden und andere Informationen zugreifen, auf die durch Reflexion zugegriffen werden kann, nur wenn sich die Klasse im selben Modul befindet, oder das Modul hat ein Paket, das für den Reflexionszugriff geöffnet ist. Dies kann über die Definitionsdatei modul-info.java Modul implementiert werden:
Modul MyModule {exportiert com.javax0.module.demo; öffnet com.javax0.module.demo;} Dieses Modul java.base ist nicht erforderlich, um es für den Reflexionszugriff alleine zu öffnen, insbesondere für unbenannte Module. Wenn wir ein Modul erstellen und es benennen, enthält die Fehlermeldung den Namen des Moduls.
Können wir Module im Programm öffnen? Das Modul java.lang.reflect.Module verfügt über eine Addopens -Methode, die durchgeführt werden kann.
Ist es machbar?
Die schlechte Nachricht für Entwickler ist: Es ist nicht machbar. Es kann nur ein Paket in einem Modul in einem anderen Modul öffnen, und das Paket wurde in diesem Modul geöffnet, indem diese Methode aufgerufen wird. Diese Methode kann es nur ermöglichen, Module an ein anderes Modulrechte zu übergeben, vorausgesetzt, das andere Modul hat das gleiche Paket in irgendeiner Weise geöffnet und keine ungeöffneten Pakete öffnen (Übersetzer Anmerkung: Es ist schwer zu verstehen, nicht wahr?).
Gleichzeitig ist die gute Nachricht: Java 9 ist nicht so einfach zu knacken wie Java 8. Zumindest ist diese Verwundbarkeit geschlossen. Es scheint, dass sich Java zu einem professionellen Niveau entwickelt, nicht nur zu einem Spielzeug (Übersetzer Anmerkung: Wer sagte, Java sei ein Spielzeug?). In naher Zukunft können Sie Projekte in RPG- und COBOL -Sprachen sehr ernst auf Java migrieren. (Entschuldigung, ich habe Witze gemacht)
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.
Dieser Artikel ist übersetzt aus: https://dzone.com/articles/hacking-the-inegercache-in-java-9