He escrito la siguiente prueba para verificar la memoria de almacenamiento dinámico máxima disponible:
import java.util.*; public class Memory { public static void main(String[] args) { long maxMB = Runtime.getRuntime().maxMemory() / 1048576L; System.out.println("Maximum memory is " + maxMB + " MB."); ArrayList<byte[]> allocated = new ArrayList<>(); try { while (true) allocated.add(new byte[1024*1024]); } catch (OutOfMemoryError e) { System.out.println("allocated " + allocated.size() + " MB before running out of memory."); } } }Sin embargo, cuando pruebo esto, parece que solo se puede asignar la mitad de la memoria "disponible":
$ java -Xmx512m Memory Maximum memory is 512 MB. allocated 255 MB before running out of memory. $ java -Xmx1024m Memory Maximum memory is 1024 MB. allocated 511 MB before running out of memory.¿Alguien sabe por qué sería así?
Creo que lo que sucede es que el administrador de memoria intenta alinear los fragmentos en el siguiente límite de 1 MB disponible. Pero como las matrices de 1 MB en realidad ocupan un poco más de 1 MB (para almacenar la longitud y otras cosas), se organizan con una brecha de casi 1 MB entre ellas. Al reducir el tamaño del bloque en 16 bytes, de repente usan toda la memoria nuevamente.