Question

Je suis à l'aide d' ByteBuffers et FileChannels pour écrire des données binaires dans un fichier.Quand vous faites que pour les gros fichiers, ou successivement pour plusieurs fichiers, j'obtiens un OutOfMemoryError exception à la règle.J'ai lu ailleurs que l'utilisation de Bytebuffers avec NIO est cassé et doit être évitée.Ne l'un de vous à déjà été confrontés à ce genre de problème et trouvé une solution efficace d'économiser de grandes quantités de données binaires dans un fichier en java?

Est l'option de la jvm -XX:MaxDirectMemorySize le chemin à parcourir?

Était-ce utile?

La solution

Je dirais de ne pas créer un énorme ByteBuffer qui contient TOUTES les données à la fois.Créer un beaucoup plus petit ByteBuffer, le remplir avec les données, puis écrire ces données dans le FileChannel.Puis réinitialiser le ByteBuffer et continuer jusqu'à ce que toutes les données sont écrites.

Autres conseils

Découvrez Java Mappé Octet Tampons, aussi connu comme 'direct tampons'.En fait, ce mécanisme utilise le système d'exploitation de l'échange de la mémoire virtuelle du système de "carte" de votre tampon directement sur le disque.Le système d'exploitation de gérer le déplacement de la octets vers/à partir du disque et de la mémoire auto-magiquement, très rapidement, et vous n'aurez pas à vous inquiéter à propos du changement de votre machine virtuelle options.Cela vous permettra également de profiter de NIO de l'amélioration de la performance sur java traditionnelle basée sur les flux d'e/s, sans aucune bizarre hacks.

Les deux seules les captures que je peux penser sont:

  1. Sur système 32 bits, vous êtes limité à un peu moins de 4 GO total pour l'ensemble des mappé octet tampons.(Qui est en fait une limite pour mon application, et je vais maintenant courir sur des architectures 64 bits.)
  2. La mise en œuvre est de la JVM spécifique et non une obligation.J'utilise du Soleil JVM et il n'y a pas de problèmes, mais YMMV.

Kirk Pepperdine (un peu célèbre la performance Java gourou) est impliqué avec un site web, www.JavaPerformanceTuning.com, qui a plus de MBB détails: NIO Conseils de Performances

Si vous accéder à des fichiers dans un mode aléatoire (lire ici, sautez, y écrire, revenir), alors vous avez un problème ;-)

Mais si vous n'en écriture de gros fichiers, vous devez sérieusement envisager d'utiliser des ruisseaux. java.io.FileOutputStream peut être utilisée directement pour écrire le fichier octet par octet ou enveloppé dans n'importe quel flux (c'est à dire DataOutputStream, ObjectOutputStream) pour la commodité de l'écriture, des flotteurs, des entiers, des Chaînes ou même serializeable objets.Des catégories similaires existent pour la lecture de fichiers.

Flux vous offrons la commodité de manipulation arbitrairement des fichiers volumineux dans (presque) arbitrairement petite mémoire.Ils sont le moyen privilégié d'accès du système de fichiers dans la grande majorité des cas.

À l'aide de la transferFrom méthode devrait aider avec ceci, en supposant que vous écrire dans le canal de façon progressive et pas tous à la fois comme les précédentes réponses également à souligner.

Cela peut varier en fonction de la JDK le fournisseur et la version.

Il y a un bug dans le GC dans certains Jvm Sun.Les pénuries de direct à la mémoire ne sera pas déclencher un GC dans le principal segment, mais le direct à la mémoire est clouée au sol par le garbage direct ByteBuffers dans le tas principal.Si le principal segment est presque vide, elles ne sont pas collectées pour un long moment.

Cela peut vous brûler, même si vous n'êtes pas à l'aide directe des tampons sur votre propre, parce que la JVM peut être la création directe tampons sur votre nom.Par exemple, l'écriture d'un non-direct ByteBuffer à un SocketChannel crée un direct tampon sous les couvertures à utiliser pour les e/S réelles de fonctionnement.

La solution de contournement consiste à utiliser un petit nombre des tampons de vous-même, et de les conserver pour les réutiliser.

Les deux précédentes réponses semblent assez raisonnables.Quant à savoir si le commutateur de ligne de commande fonctionne, il dépend de la façon dont rapidement votre utilisation de la mémoire arrive à la limite.Si vous n'avez pas assez de ram et de mémoire virtuelle disponible pour au moins le triple de la quantité de mémoire disponible, alors vous aurez besoin d'utiliser l'une de l'autre suggestions.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top