Ejecutar el siguiente código en Windows 10 / OpenJDK 11.0.4_x64 produce como salida used: 197
y expected usage: 200
. Esto significa que las matrices de 200 bytes de un millón de elementos ocupan aprox. 200 MB de RAM. Todo bien
Cuando cambio la asignación de la matriz de bytes en el código de new byte[1000000]
a new byte[1048576]
(es decir, a 1024 * 1024 elementos), se produce como salida used: 417
y expected usage: 200
. ¿Que demonios?
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();
}
}
Mirando un poco más profundo con visualvm, veo en el primer caso todo como se esperaba:
En el segundo caso, además de las matrices de bytes, veo el mismo número de matrices int que ocupan la misma cantidad de RAM que las matrices de bytes:
Estas matrices int, por cierto, no muestran que estén referenciadas, pero no puedo recolectarlas de forma basura ... (Las matrices de bytes muestran muy bien dónde están referenciadas).
¿Alguna idea de lo que está pasando aquí?
int[]
para emular una byte[]
localidad espacial grande y mejor?