2009-07-15 13 views
9

Ho ereditato un certo codice:Process Builder waitFor() di emissione e di file Open limitazioni

Process p = new ProcessBuilder("/bin/chmod", "777", path).start(); 
p.waitFor(); 

In sostanza, non v'è per qualche motivo basato voodoo antica e fortemente per la memorizzazione di coppie chiave/valore su disco come file. Non voglio davvero entrarci.

Tuttavia, io sono rimasto con una serie di eccezioni IO:

Exception :Cannot run program "/bin/chmod": java.io.IOException: error=24, Too many open files 
Message: Cannot run program "/bin/chmod": java.io.IOException: error=24, Too many open files 

E da un gruppo intendo nei regni di 10k - milioni

ho la sensazione della chiamata waitFor era fermare questi si verificano in attesa che il processo lo completi e si ritiri, tuttavia penso che chmod restituisca un risultato prima che il file sia effettivamente chiuso. Qualcuno sa se questa sarebbe la causa di queste eccezioni?

La mia altra inclinazione è che l'apertura e la chiusura di migliaia di file non sta accadendo abbastanza velocemente sul java e che c'è qualcos'altro che sta succedendo, forse qualcosa di simile c'è qualche forma di buffer di file che non è viene cancellato quando viene chiamato fw.close().

Sono piuttosto nuovo di java e questo è stato un inferno strano che mi ha lasciato perplesso. (volentieri l'app funziona ancora .. dopo aver sputato un file di registro molto grande)

Qualcun altro può pensare a un modo per aggirare questo problema, eliminare i buffer o aumentare il limite di apertura dei file a qualcosa in cui la jvm può tenere il passo con se stesso (supponendo che questo sia il problema)

+0

Qual è il sistema operativo di destinazione (e la versione).Vedere questo: http://unix.derkeiler.com/Newsgroups/comp.unix.solaris/2007-02/msg00873.html –

+0

debian, sembra essere cancellato da uname. sarà l'ultima stabile. – Louis

risposta

14

Suppongo che tu stia eseguendo questi comandi chmod in un ciclo, altrimenti non vedo perché potresti ottenere così tante eccezioni. È possibile che tu stia colpendo un deadlock perché non stai leggendo l'output dei processi generati. Che sicuramente mi mordeva nei giorni precedenti allo ProcessBuilder, Runtime.exec().

Cambia lo snippet di codice per il modello di cui sopra:

try { 
    ProcessBuilder pb = new ProcessBuilder("/bin/chmod", "777", path);  
    pb.redirectErrorStream(true); // merge stdout, stderr of process 

    Process p = pb.start(); 
    InputStreamReader isr = new InputStreamReader(p.getInputStream()); 
    BufferedReader br = new BufferedReader(isr); 

    String lineRead; 
    while ((lineRead = br.readLine()) != null) { 
     // swallow the line, or print it out - System.out.println(lineRead); 
    } 

    int rc = p.waitFor(); 
    // TODO error handling for non-zero rc 
} 
catch (IOException e) { 
    e.printStackTrace(); // or log it, or otherwise handle it 
} 
catch (InterruptedException ie) { 
    ie.printStackTrace(); // or log it, or otherwise handle it 
} 

(credito: this site) e vedere se questo aiuta la situazione.

+0

Provato questo, si verificano le stesse eccezioni – Louis

+0

Penso di averlo risolto controllare la mia risposta in pochi minuti - aspettando solo i test per verificare – Louis

+0

Ok scelto il tuo come risposta in quanto aveva bisogno di questo nella soluzione , controlla il mio post includerà le linee aggiuntive necessarie. – Louis

0

Sembra improbabile che il processo venga completato senza chiudere i file. Questo potrebbe accadere in un numero molto grande di thread? O forse alcuni di loro non stanno effettivamente completando (cioè, è sospeso in attesa, in alcuni casi)?

In caso contrario, penso che si sarà bloccato con l'aumento del limite di file aperti. Supponendo che questo sia un sistema simile a Unix, il comando "ulimit" è probabilmente quello che stai cercando.

+0

impostato su illimitato: \ – Louis

0

Se si utilizza JAVA 6, è anche possibile provare i nuovi setter (per lettura, scrittura, esecuzione) sull'oggetto File. Potrebbe essere più lento, ma dovrebbe funzionare.

6

Grazie per l'aiuto ragazzi, questo dovrebbe risolvere un carico di stranezze in corso altrove a causa di esso.

Usando il tuo esempio (Vinay) e le chiusure di flusso:

try{ 
    fw.close(); 

    ProcessBuilder pb = new ProcessBuilder("/bin/chmod", "777", path); 

    pb.redirectErrorStream(true); // merge stdout, stderr of process 
    p = pb.start(); 

    InputStreamReader isr = new InputStreamReader(p.getInputStream()); 
    BufferedReader br = new BufferedReader(isr); 

    String lineRead; 
    while ((lineRead = br.readLine()) != null) { 
    // swallow the line, or print it out - System.out.println(lineRead); 
    } 

} catch (Exception ioe) { 
    Logger.logException(Logger.WARN, ioe.getMessage(), ioe); 
} finally { 
    try { 
    p.waitFor();//here as there is some snipped code that was causing a different 
       // exception which stopped it from getting processed 

    //missing these was causing the mass amounts of open 'files' 
    p.getInputStream().close(); 
    p.getOutputStream().close(); 
    p.getErrorStream().close(); 

    } catch (Exception ioe) { 
    Logger.logException(Logger.WARN, ioe.getMessage(), ioe); 
    } 
} 

avuto l'idea da John B Mathews post.

+0

nota: ancora non ha senso perché avere l'attesa Per chiudere i flussi di input non andrebbe bene ma immagino che sia java ... – Louis

+1

Buona cattura, jim, ma continuo a vedere un problema nel tuo 'finalmente' . Penso che sia necessario avere ciascuna delle chiamate 'close' nel proprio' catch ', altrimenti se si verifica un'eccezione quando si esegue 'p.getInputStream.close()', non si riesce a chiudere gli altri. Il problema potrebbe sembrare essere andato via ora, ma potrebbe tornare più tardi. –

+0

buon punto. grazie – Louis