Bonjour tout le monde,

Quelque chose m'échappe dans la gestion de la mémoire de Java. Je ne comprends pas pourquoi j'obtiens une OutOfMemoryError alors qu'il semble pourtant qu'il y ai assez de mémoire disponible.

Voici un exemple de code générant un OutOfMemoryError (avec les paramètres Xms et Xmx par défaut) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package testheapsize;
 
import java.util.logging.Level;
import java.util.logging.Logger;
 
public class Main {
 
    public static void main(String... args) {
        try {
            long size = 178868493;
 
            Runtime runtime = Runtime.getRuntime();
            long free0 = runtime.freeMemory();
            System.out.println(size + " : " + free0 + " / " + runtime.totalMemory());
            byte[] fileBytes = new byte[(int) size];
            long free1 = runtime.freeMemory();
            System.out.println(size + " : " + free1 + " / " + runtime.totalMemory());
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
Ce que j'obtiens donc est la chose suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
178868493 : 15964944 / 16252928
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at testheapsize.Main.main(Main.java:15)
Java Result: 1
Soit, pourquoi pas.

Cependant, si au lieu de 178868493 je mets 178868492 (donc 1 octet de différence) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package testheapsize;
 
import java.util.logging.Level;
import java.util.logging.Logger;
 
public class Main {
 
    public static void main(String... args) {
        try {
            long size = 178868492;
 
            Runtime runtime = Runtime.getRuntime();
            long free0 = runtime.freeMemory();
            System.out.println(size + " : " + free0 + " / " + runtime.totalMemory());
            byte[] fileBytes = new byte[(int) size];
            long free1 = runtime.freeMemory();
            System.out.println(size + " : " + free1 + " / " + runtime.totalMemory());
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
J'obtiens alors le résultat suivant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
178868492 : 15964944 / 16252928
178868492 : 79111016 / 259522560
J'ai donc 79111016 octets de disponible après création de mon tableau. Or dans le premier cas où j'augmente sa taille de seulement 1, la JVM me dit qu'elle n'a pas assez de place !

Quelque chose m'échappe. Quelqu'un peut-il m'aiguiller sur les raisons de ce fonctionnement ?

Merci d'avance !