Uruchomienie poniższego kodu w systemie Windows 10 / OpenJDK 11.0.4_x64 powoduje wygenerowanie danych wyjściowych used: 197
i expected usage: 200
. Oznacza to, że 200 bajtów tablic z milionem elementów zajmuje około. 200 MB pamięci RAM. Wszystko w porządku.
Kiedy zmienię przydział tablicy bajtów w kodzie z new byte[1000000]
na new byte[1048576]
(to znaczy na 1024 * 1024 elementów), to generuje jako dane wyjściowe used: 417
i expected usage: 200
. Co za cholera?
import java.io.IOException;
import java.util.ArrayList;
public class Mem {
private static Runtime rt = Runtime.getRuntime();
private static long free() { return rt.maxMemory() - rt.totalMemory() + rt.freeMemory(); }
public static void main(String[] args) throws InterruptedException, IOException {
int blocks = 200;
long initiallyFree = free();
System.out.println("initially free: " + initiallyFree / 1000000);
ArrayList<byte[]> data = new ArrayList<>();
for (int n = 0; n < blocks; n++) { data.add(new byte[1000000]); }
System.gc();
Thread.sleep(2000);
long remainingFree = free();
System.out.println("remaining free: " + remainingFree / 1000000);
System.out.println("used: " + (initiallyFree - remainingFree) / 1000000);
System.out.println("expected usage: " + blocks);
System.in.read();
}
}
Patrząc nieco głębiej w visualvm, w pierwszym przypadku widzę wszystko zgodnie z oczekiwaniami:
W drugim przypadku oprócz tablic bajtowych widzę tę samą liczbę tablic int zajmujących taką samą ilość pamięci RAM, jak tablice bajtów:
Nawiasem mówiąc, te tablice int nie pokazują, że są do nich odniesienia, ale nie mogę ich wyrzucać do śmieci ... (Tablice bajtów pokazują dobrze, gdzie są odniesienia).
Jakieś pomysły, co się tutaj dzieje?
int[]
polecenia emulacji dużej byte[]
dla lepszej lokalizacji przestrzennej?