Bei der herkömmlichen Java-Programmierung müssen Sie sich nicht mehr mit Java-Objekten oder Speicherorten aus dem Speicher befassen. Wenn Sie dies in Foren diskutieren, stellt sich zunächst die Frage: Warum müssen Sie die Adresse eines Java-Objekts kennen? Es ist eine berechtigte Frage. Aber in der Vergangenheit haben wir uns das Recht vorbehalten, Versuche durchzuführen. Es ist nichts Falsches daran, Fragen auf unbekanntem Terrain zu untersuchen. Ich habe mir ein Experiment mit Sun-Firmenpaketen ausgedacht. Unsafe ist ein Paket, das zu sun.misc gehört. Vielleicht ist Ihnen dieses Paket etwas unbekannt. Schauen Sie sich den Quellcode und die Methoden an und Sie werden wissen, was ich meine.
Das Sicherheitsmanagement von Java bietet genügend Versteckmöglichkeiten, um sicherzustellen, dass Sie nicht so leicht mit dem Speicher herumspielen können. Als ersten Schritt dachte ich darüber nach, den Speicherort eines Java-Objekts zu ermitteln. Bis zur Erkundung war ich zu 100 % davon überzeugt, dass es in Java unmöglich ist, den Standort der Adresse eines Objekts zu finden.
Die Unsafe.java-API-Dokumentation von Sun zeigt, dass wir über die Methode objectFieldOffset Zugriff auf die Adresse haben. Diese Methode scheint zu sagen: „Die Klasse im Bericht weist ihren Speicherort in einem bestimmten Speicherbereich zu.“ Sie sagt auch: „Dies ist nur ein Accessor, bei dem das Cookie an den unsicheren Heap-Speicher übergeben wird.“ Wie auch immer, ich kann den Speicherort, an dem ein Objekt gespeichert wird, aus dem Speicher seiner Klasse zuweisen. Man könnte argumentieren, dass wir nicht die absolute physische Speicheradresse eines Objekts erhalten. Wir haben jedoch die logische Speicheradresse erhalten. Das folgende Programm wird für Sie von großem Interesse sein!
Als ersten Schritt muss ich mir ein Objekt der Unsafe-Klasse besorgen. Dies ist schwierig, da die Konstrukteure privat sind. Es gibt eine Methode namens getUnsafe, die ein unsicheres Objekt zurückgibt. Für die Java-Sicherheitsverwaltung ist es erforderlich, Quellcode-Berechtigungen zu erteilen. Ich habe ein wenig nachgedacht und eine Instanz erhalten. Ich weiß, dass es bessere Möglichkeiten gibt, eine Instanz zu erhalten, aber ich habe die folgende Methode gewählt, um die Sicherheitsverwaltung zu umgehen.
Um unsichere Objekte zu verwenden, rufen Sie einfach objectFieldOffset und staticFieldOffset auf. Das Ergebnis ist die Speicherzuordnungsadresse der Klasse.
Das folgende Beispielprogramm kann auf JDK1.6 ausgeführt werden.
öffentliche Klasse ObjectLocation {
private static int apple = 10;
private int orange = 10;
public static void main(String[] args) löst eine Ausnahme aus {
Unsicher unsafe = getUnsafeInstance();
Feld appleField = ObjectLocation.class.getDeclaredField("apple");
System.out.println("Standort von Apple: "
+ unsafe.staticFieldOffset(appleField));
Feld orangeField = ObjectLocation.class.getDeclaredField("orange");
System.out.println("Standort von Orange: "
+ unsafe.objectFieldOffset(orangeField));
}
private static Unsafe getUnsafeInstance() löst eine SecurityException aus,
NoSuchFieldException, IllegalArgumentException,
IllegalAccessException {
Feld theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafeInstance.setAccessible(true);
return (Unsafe) theUnsafeInstance.get(Unsafe.class);
}
}