web-dev-qa-db-fra.com

Mémoire tampon direct

J'ai besoin de retourner un fichier plutôt volumineux d'une demande Web. Le fichier est d'environ 670 Mo de taille. Pour la plupart, cela fonctionnera bien, mais après un certain temps, l'erreur suivante sera lancée:

Java.lang.OutOfMemoryError: Direct buffer memory
    at Java.nio.Bits.reserveMemory(Bits.Java:694) ~[na:1.8.0_162]
    at Java.nio.DirectByteBuffer.<init>(DirectByteBuffer.Java:123) ~[na:1.8.0_162]
    at Java.nio.ByteBuffer.allocateDirect(ByteBuffer.Java:311) ~[na:1.8.0_162]
    at Sun.nio.ch.Util.getTemporaryDirectBuffer(Util.Java:241) ~[na:1.8.0_162]
    at Sun.nio.ch.IOUtil.read(IOUtil.Java:195) ~[na:1.8.0_162]
    at Sun.nio.ch.FileChannelImpl.read(FileChannelImpl.Java:159) ~[na:1.8.0_162]
    at Sun.nio.ch.ChannelInputStream.read(ChannelInputStream.Java:65) ~[na:1.8.0_162]
    at Sun.nio.ch.ChannelInputStream.read(ChannelInputStream.Java:109) ~[na:1.8.0_162]
    at Sun.nio.ch.ChannelInputStream.read(ChannelInputStream.Java:103) ~[na:1.8.0_162]
    at Java.nio.file.Files.read(Files.Java:3105) ~[na:1.8.0_162]
    at Java.nio.file.Files.readAllBytes(Files.Java:3158) ~[na:1.8.0_162]

J'ai défini la taille du tas sur 4096 Mo, que je pense devoir être suffisamment grande pour gérer ce genre de fichiers. En outre, lorsque cette erreur s'est produite, j'ai pris un tas de châssis avec Jmap pour analyser l'état actuel. J'ai trouvé deux autres octets plutôt grands [], ce qui devrait être le fichier que je veux revenir. Mais le tas est seulement environ 1,6 Go de taille et non près de la configuration de 4 Go, cela peut être.

Selon une autre réponse (- https://stackoverflow.com/a/39984276/5126654 ) Dans une question similaire, j'ai essayé de faire fonctionner le GC manuel avant de renvoyer ce fichier. Le problème est toujours survenu mais maintenant seulement spardique. Le problème s'est produit après un certain temps, mais lorsque je me suis fatigué de courir la même demande, il semble que la collection des ordures ait pris soin de tout ce qui a provoqué le problème, mais cela ne suffit pas car le problème peut encore se produire. Y a-t-il une autre façon d'éviter ce problème de mémoire?

4
Stephan Stahlmann

Vous pouvez également essayer d'augmenter la taille du tampon utilisé pour DirectBytBuffer avec l'option JVM -XX:MaxDirectMemorySize. Le Java Docs ne sont pas très détaillés sur ce paramètre, mais selon ceci page Il sera défini par défaut sur 64 Mo, sauf si vous avez spécifié le -Xmx drapeau. Donc, si vous n'avez pas défini ce drapeau, le tampon alloué peut être trop petit. Ou si vous avez un très grand fichier et avez défini -Xmx, le 2GB dérivé peut être trop petit et vous pourriez toujours bénéficier d'un tampon plus grand manuellement.

Dans l'ensemble, la meilleure approche si probablement pour diffuser le fichier comme suggéré par Stephen C.

0
Erik Finnman