V tomto krátkém článku si ukážeme, že i v
Javě (přesněji Sun JDK) můžeme používat ukazatelovou
aritmetiku. Nehledejte v tom však něco praktického.
Jde spíše o exkurzi do méně známých končin JDK.
Celé kouzlo je schováno ve tříde sun.misc.Unsafe
. Tato třída umožňuje např.
přímý přístup do paměti, atomické operace s pamětí
(Compare and Swap), kopírování obsahu paměti,
zamykání objektů a „parkování“ vláken.
Třída sun.misc.Unsafe
má pouze
privátní konstruktor, takže její instanci nelze
vytvořit přímo. Získáme ji ze statického atributu
theUnsafe
této třídy pomocí reflection (metoda getUnsafe
).
Dále naalokujeme paměť (metoda allocateMemory
) a s použitím ukazatelové
aritmetiky do této paměti zapíšeme (metoda writeToMem
). Nakonec obsah paměti zobrazíme
(metoda printMem
).
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class PF2010 {
public static void main(String[] args) {
byte[] magic = {80, 70, 32, 50, 48, 49, 48, 33};
try {
Unsafe u = getUnsafe();
int len = magic.length * 2;
long adr = u.allocateMemory(len);
writeToMem(u, adr, magic);
printMem(u, adr, len);
} catch (Exception e) {
e.printStackTrace();
}
}
static Unsafe getUnsafe() throws Exception {
Class c = Unsafe.class;
Field f = c.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
}
static void writeToMem(Unsafe u, long p, byte[] values) {
for (byte b : values) {
u.putChar(p, (char) b);
p += 2;
}
}
static void printMem(Unsafe u, long p, int len) {
int n = len / 2;
for (; n > 0; n--) {
char c = u.getChar(p);
System.out.print(c);
p += 2;
}
System.out.println();
}
}