2011-05-24 3 views
5

Salut, j'ai un code qui utilise bloquerréduire le nombre de fichiers ouverts dans le code java

RandomAccessFile file = new RandomAccessFile("some file", "rw"); 
FileChannel channel = file.getChannel(); 

// some code 
String line = "some data"; 
ByteBuffer buf = ByteBuffer.wrap(line.getBytes()); 
channel.write(buf); 

channel.close(); 
file.close(); 

mais spécifique de l'application est que je dois en moyenne pour générer un grand nombre de fichiers temporaires, plus de 4000 (utilisé pour les insertions Hive sur la table partitionnée).

Le problème est que, parfois, je prends exception

Failed with exception Too many open files 

lors de l'application lancée.

Je wounder s'il y a une façon de dire OS que le fichier est déjà fermé et ne sont plus utilisés, pourquoi le

channel.close(); 
file.close(); 

ne réduit pas le nombre de dossiers ouverts. Y at-il un moyen de le faire dans le code Java?

Je l'ai déjà augmenté nombre maximum de fichiers ouverts dans

#/etc/sysctl.conf: 
kern.maxfiles=204800 
kern.maxfilesperproc=200000 
kern.ipc.somaxconn=8096 

Mise à jour: J'ai essayé d'éliminer le problème, donc je sépara le code pour enquêter sur chaque partie (créer des fichiers, télécharger vers ruche, supprimer des fichiers). L'utilisation de la classe 'Fichier' ou 'RandomAccessFile' échoue avec l'exception "Trop de fichiers ouverts".

Enfin j'ai utilisé le code:

FileOutputStream s = null; 
FileChannel c = null; 

try { 
    s = new FileOutputStream(filePath); 
    c = s.getChannel(); 
    // do writes 
    c.write("some data"); 
    c.force(true); 
    s.getFD().sync(); 

} catch (IOException e) { 
    // handle exception 
} finally { 
    if (c != null) 
     c.close(); 
    if (s != null) 
     s.close(); 
} 

Et cela fonctionne avec de grandes quantités de fichiers (testé sur 20K avec la taille de chaque 5KB). Le code lui-même ne lance pas d'exception en tant que deux classes précédentes. Mais le code de production (avec ruche) avait toujours l'exception. Et il semble que la connexion de la ruche à travers le JDBC en soit la raison. Je vais enquêter plus loin.

+0

Cela ressemble à quelque chose dépend du finaliseur pour fermer les ressources externes. C'est ... demander des ennuis vraiment. –

Répondre

4

La quantité de handles de fichiers ouverts pouvant être utilisés par le système d'exploitation n'est pas la même chose que le nombre de handles de fichiers pouvant être ouverts par un processus. La plupart des systèmes Unix limitent le nombre de handles de fichiers par processus. Très probablement quelque chose comme 1024 poignées de fichiers pour votre JVM. A) Vous devez définir l'ulimit dans le shell qui lance la JVM à une valeur plus élevée. (Quelque chose comme 'ulimit -n 4000')

b) Vous devez vérifier que vous n'avez aucune fuite de ressources qui empêchent vos fichiers d'être «finalisés».

0

Est-ce le code exact? Parce que je peux penser à un scénario où vous pourriez ouvrir tous les fichiers dans une boucle et écrit le code pour les fermer à la fin qui cause ce problème. S'il vous plaît poster le code complet.

+0

Le mode d'utilisation est le suivant: 1) Obtenir les données de la source mysql vers certains objets de données 2) Faire une boucle sur la liste des objets et faire à chaque itération le code affiché. Donc, je fais la paix du code affiché dans chaque itération et ne pas avoir tous les fichiers ouverts une seule fois. – ykhrustalev

3

Assurez-vous d'utiliser un bloc finally {}. S'il y a une exception pour une raison quelconque, la fermeture ne se produira jamais dans le code tel qu'il est écrit.