2012-05-04 16 views
17

Ho esaminato altre domande simili su SO, ma sembrano essere causate da altri problemi.JDK 1.7: "Troppi file aperti" a causa dei semafori POSIX?

Per prima cosa mi sono assicurato di chiudere con giudizio tutti i miei handle di file, quindi ho utilizzato lsof -p <pid of java> per consultare il mio elenco di file.

rimane abbastanza costante durante tutto il mio tempo di esecuzione, ma poi periodicamente mi metterò circa 10.000 voci elencate in lsof come questo:

COMMAND PID USER FD  TYPE DEVICE SIZE/OFF  NODE NAME 
             ... 
java 36809 smm *235r PSXSEM    0t0   kcms00008FC901624000 
java 36809 smm *236r PSXSEM    0t0   kcms00008FC901624000 
java 36809 smm *237r PSXSEM    0t0   kcms00008FC901624000 
java 36809 smm *238r PSXSEM    0t0   kcms00008FC901624000 
java 36809 smm *239r PSXSEM    0t0   kcms00008FC901624000 

La pagina man dice PSXSEM tipo è un POSIX semaforo. Qualche indizio su cosa JDK usa per i semafori POSIX? A proposito, l'app è una app a linea di comando a thread singolo al momento.

potenzialmente utile sfondo: in primo luogo ho notato questo dopo l'aggiornamento a JDK 1.7 su Mac OS X 10.7.3:

java version "1.7.0_04" 
Java(TM) SE Runtime Environment (build 1.7.0_04-b21) 
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode) 

Aggiornamento: repointing $JAVA_HOME al JDK 1.6 sembra essere una soluzione per il problema.

java version "1.6.0_31" 
Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635) 
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode) 

Che cosa fa JDK 1.7 in modo diverso?

+0

Vorrei provare un java profiler regolare, come YourTrack o anche solo VisualVM per vedere se è possibile correlare la creazione dei semafori 10K alla creazione di un gran numero di oggetti libreria Java. –

+2

Sto ancora vedendo questo problema, ma non sto usando ImageIO (almeno non direttamente). I ripristini fanno sì che il numero di semafori aumenti, fino a quando ottengo un: 2012-05-09 16: 30: 12.856 java [14407: 3d87] UI persistente non è riuscito ad aprire il file file: // localhost/Users/juancn/Library /Saved%20Application%20State/net.java.openjdk.cmd.savedState/window_1.data: Troppi file aperti (24) – juancn

risposta

7

ho potuto rintracciare giù a questo blocco di codice:

BufferedImage image = null; 
ImageInputStream stream = null; 
try { 
    stream = new FileImageInputStream(file); 
    image = ImageIO.read(stream); 

} catch (Exception ex) { 
    log.error("Image could not be read: "+file.getPath()); 

} finally { 
    // ImageIO closes input stream unless null is returned 
    // http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#read(javax.imageio.stream.ImageInputStream) 
    if (stream != null && image == null) { 
     try { 
      stream.close(); 
     } catch (IOException ex) { 
      log.error("ERROR closing image input stream: "+ex.getMessage(), ex); 
     } 
    } 
} 

I JavaDocs specificamente dire che questo metodo (a differenza degli altri) chiude il flusso automaticamente. Infatti, quando si tenta di chiuderlo manualmente, si genera un'eccezione che dice 'chiuso'. Stavo usando questo sovraccarico poiché l'altro dice che lo avvolge in un ImageInputStream comunque ho pensato di risparmiare un po 'di lavoro.

Cambiare il blocco di utilizzare una normale FileInputStream fissa la perdita:

BufferedImage image = null; 
InputStream stream = null; 
try { 
    stream = new FileInputStream(file); 
    image = ImageIO.read(stream); 

} catch (Exception ex) { 
    log.error("Image could not be read: "+file); 

} finally { 
    if (stream != null) { 
     try { 
      stream.close(); 
     } catch (IOException ex) { 
      log.error("ERROR closing image input stream: "+ex.getMessage(), ex); 
     } 
    } 
} 

Questo mi sembra essere un bug nel JDK 1.7 come 1.6 ha funzionato bene qui.

Aggiornamento: Sono appena submitted a bug report su Oracle per questo problema.

+0

sfortunatamente non sembra essere corretto a partire dalla versione 1.7.0_04, è troppo male anche se non c'è altro API nella specifica che consentono di verificare la validità di un'immagine. Comunque, immagino che tu sia fortunato, sto ancora ottenendo quei semafori che continuano a uccidere il container JEE. –

+0

@ArchimedesTrajano Ho ancora avuto problemi intermittenti anche con questo lavoro in giro, anche. Sembra essere un bug piuttosto brutto. – mckamey

+0

È solo su file JPEG. Poiché io uso solo per verificare se un file JPEG è "valido", controllo solo se ha l'inizio dell'immagine e la fine dell'immagine nei punti appropriati. –

4

Ho trovato un'altra causa. Sembra che il metodo toRGB() di ColorSpace stia perdendo semafori. L'esecuzione del seguente codice:

import java.awt.color.ColorSpace; 
public class Test 
{ 
    public static void main(String[] args) throws Throwable { 
     final ColorSpace CIEXYZ = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ); 
     for(int i = 0; i < 10000000; i++) { 
      CIEXYZ.toRGB(new float[] {80f, 100, 100}); 
     } 
    } 
} 

Con:

java version "1.7.0_04" 
Java(TM) SE Runtime Environment (build 1.7.0_04-b21) 
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode) 

lascerete fuori dei file di sistema.

EDIT: già presentato un bug report a Oracle

+0

Bella scoperta. Grazie. – mckamey

4

Aggiornamento: Come altri utenti hanno detto, ImageIO perdeva semafori in 1.7.0_04 e 1.7.0_05. Le segnalazioni di bug dell'utente juancn e dell'utente mckamey sono state contrassegnate come fisse e chiuse (grazie ragazzi!).La spiegazione:

Questa correzione riporta una perdita di gestori di file su macosx. Ha menzionato due modi per individuare gli handler: tramite ImageIO.read (ImageInputStream) e tramite semafori.

Non osservo la prima perdita: chiudiamo esplicitamente il flusso di input se troviamo un lettore appropriato, e questo è sufficiente (almeno sulla 1.7.4) per rilasciare gli handle di file.

Tuttavia, in caso di semafori che perdita di tonnellate di maniglie: eseguiamo la conversione del colore per ogni linea di immagine jpeg, e ogni volta che creiamo un semaforo (perché vediamo 2 o più CPU installata nel sistema), quindi riduciamo il numero di attività separate fino a 1 (poiché abbiamo una singola linea di scansione da elaborare) e, a causa di ciò, non scolleghiamo mai il semaforo.

Lo stesso problema è presente nei sistemi Linux, ma in misura minore perché occupiamo un singolo handle di file per ogni semaforo denominato, mentre su macosx occupiamo sempre il nuovo handle di file.

correzione suggerita proprio pospone la creazione di nome semaforo fino a quando chiariamo il numero di compiti separati, così, ora non creiamo i semafori per la lettura delle immagini e semplice colore conversioni (come ColorSpace.toRGB()). Oltre a questo, ora usiamo il puntatore pSem come trigger per la distruzione del semaforo.

Anche se i loro rapporti indicano che la correzione è in versione 8, un rapporto backport indica che è stato fixed in 1.7.0_06.

Quindi, se stai vedendo questo in 1.7.0_04 o 05, l'aggiornamento ad almeno 1,7 .0_06 si prenderà cura di questo problema.

Problemi correlati