L'exécution du code ci-dessous sur Windows 10 / OpenJDK 11.0.4_x64 produit en sortie used: 197
et expected usage: 200
. Cela signifie que des tableaux de 200 octets d'un million d'éléments occupent env. 200 Mo de RAM. Tout va bien.
Lorsque je modifie l'allocation du tableau d'octets dans le code de new byte[1000000]
à new byte[1048576]
(c'est-à-dire à 1024 * 1024 éléments), il produit en sortie used: 417
et expected usage: 200
. Que diable?
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();
}
}
En regardant un peu plus en profondeur avec visualvm, je vois dans le premier cas tout comme prévu:
Dans le deuxième cas, en plus des tableaux d'octets, je vois le même nombre de tableaux int qui occupent la même quantité de RAM que les tableaux d'octets:
Soit dit en passant, ces tableaux int ne montrent pas qu'ils sont référencés, mais je ne peux pas les récupérer ... (Les tableaux d'octets montrent très bien où ils sont référencés.)
Des idées ce qui se passe ici?
int[]
pour émuler un grand byte[]
pour une meilleure localité spatiale?