J'ai un programme qui doit allouer de l'espace de tas pour un très gros objet, mais je trouve que j'obtiens OutOfMemoryException
s quand il semble y avoir beaucoup plus de tas libre que ce gros objet devrait exiger.Comment laisser PSOldGen se développer pour accueillir des objets très volumineux?
Ce programme de test illustre le problème:
public class HeapTest {
public static void main(String[] args) {
final int size = Integer.parseInt(args[0]);
System.out.println(size >> 20);
final byte[] buf = new byte[size];
System.out.println(buf.length);
}
}
Si je cours comme java -Xmx40M -XX:+PrintGCDetails HeapTest 28000000
, je reçois la sortie suivante:
26
[GC [PSYoungGen: 317K->176K(9216K)] 317K->176K(36544K), 0.0007430 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
[GC [PSYoungGen: 176K->144K(9216K)] 176K->144K(36544K), 0.0004650 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC [PSYoungGen: 144K->0K(9216K)] [PSOldGen: 0K->115K(9216K)] 144K->115K(18432K) [PSPermGen: 2710K->2710K(21248K)], 0.0053960 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC [PSYoungGen: 0K->0K(9216K)] 115K->115K(36544K), 0.0002010 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC [PSYoungGen: 0K->0K(9216K)] [PSOldGen: 115K->112K(15104K)] 115K->112K(24320K) [PSPermGen: 2710K->2708K(21248K)], 0.0078150 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at HeapTest.main(HeapTest.java:5)
Heap
PSYoungGen total 9216K, used 476K [0x00000000ff2b0000, 0x0000000100000000, 0x0000000100000000)
eden space 7936K, 6% used [0x00000000ff2b0000,0x00000000ff327190,0x00000000ffa70000)
from space 1280K, 0% used [0x00000000ffa70000,0x00000000ffa70000,0x00000000ffbb0000)
to space 1280K, 0% used [0x00000000ffec0000,0x00000000ffec0000,0x0000000100000000)
PSOldGen total 27328K, used 112K [0x00000000fd800000, 0x00000000ff2b0000, 0x00000000ff2b0000)
object space 27328K, 0% used [0x00000000fd800000,0x00000000fd81c378,0x00000000ff2b0000)
PSPermGen total 21248K, used 2815K [0x00000000f3000000, 0x00000000f44c0000, 0x00000000fd800000)
object space 21248K, 13% used [0x00000000f3000000,0x00000000f32bff48,0x00000000f44c0000)
Le tableau que je suis en train de créer devrait être d'environ 27344K , qui dépasse légèrement la taille de l'espace objet PSOldGen. Cependant, l'espace total inutilisé est d'environ 54000K, ce qui est presque deux fois ce qui est nécessaire pour mon tableau. Comme mon programme (réel) fonctionne sur le tableau in-situ, il n'utilise pratiquement pas de mémoire au-delà de ce qui est requis pour le tableau, alors allouer deux fois la mémoire dont j'ai besoin et en utiliser seulement la moitié me semble inutile.
Y a-t-il un moyen de convaincre la JVM de laisser l'ancienne génération se développer plus qu'elle ne le pourrait par défaut?
Etes-vous sûr qu'il est '-XX: NewSize' au lieu de' -XX: MaxNewSize' que je veux? Le premier est la limite inférieure, d'après ce que j'ai lu. – uckelman
Non, je ne suis pas sûr - faites aussi vos propres recherches et tests, je vous indiquais juste dans la bonne direction. ;-) "NewSize" a fait fonctionner votre code sur ma machine, mais "MaxNewSize" semble plus logique pour vous, c'est vrai. –
La raison pour laquelle j'ai demandé est que '-XX: NewSize' n'a pas fonctionné pour moi, mais' -XX: MaxNewSize' l'a fait. Est-ce que '-XX: MaxNewSize' fonctionne pour vous? J'espérais une solution qui fonctionne partout, puisque celle-ci sera déployée sur les machines de l'utilisateur. – uckelman