2017-02-21 3 views
0

Ich bin vor Probleme mit einem meiner Anwendung, und stieß auf die folgende Ausnahme, wenn eine große Menge an Transaktionsabwicklung, die Datei und Lesen des Inhalts beinhaltet öffnen: in javaMuss ich FileInputStream manuell in diesem Code schließen?

java.io.FileNotFoundException: /keystore-sample/keystore.jks (Too many open files) 

Ich habe die folgende Beispielcode geschrieben:

try { 
    EncryptDecryptPassword crypt = new EncryptDecryptPassword(); 
    String secretKey = "secret123"; 
    String trustpassencrypted = "ecnrypted1234"; 
    String trustpass = crypt.decryptPassword(trustpassencrypted.trim(), secretKey.trim()); 

    File truststore = new File("/keystore-sample/keystore.jks");  
    KeyStore keyStore = KeyStore.getInstance("JKS");  
    keyStore.load(new FileInputStream(truststore), trustpass.toCharArray()); 
    //Continue with the rest of the code... 

} catch (KeyStoreException kse) {    
    System.out.println("Security configuration failed with the following: " + kse.getCause());   
} catch (NoSuchAlgorithmException nsa) {    
    System.out.println("Security configuration failed with the following: " + nsa.getCause());   
} catch (FileNotFoundException fnfe) {    
    System.out.println("Security configuration failed with the following: " + fnfe.getCause());   
} catch (UnrecoverableKeyException uke) {    
    System.out.println("Security configuration failed with the following: " + uke.getCause());   
} catch (CertificateException ce) {    
    System.out.println("Security configuration failed with the following: " + ce.getCause());   
}catch (IOException ioe) {    
    System.out.println("Security configuration failed with the following: " + ioe.getCause());   
} 

wie Sie sehen können, habe ich eine neue Instanz für FileInput- Strom nicht erklären, wie die folgenden:
Korrektur: Meines Absicht ist, zum Ausdruck bringen, dass ich nicht die neu erstellte Fileinputstream in einer Variablen zugewiesen haben und es später manuell schließen, wie folgt aus:

FileInputStream in = new FileInputStream(truststore); 
keyStore.load(in, trustpass.toCharArray()); 
//once done with the input stream, close it 
in.close(); 

Meine Frage ist: wird new Fileinputstream (Trusts) erfordert tatsächlich manuellen Schließen oder es wird von der zugrunde liegenden Keystore-Klasse behandelt werden? Kurzer Blick auf den zugrunde liegenden dekompilierten Code von Keystore.class, ich sehe das nicht. Nur um zu bestätigen, dass dies der besondere Grund ist, warum ich die Ausnahme treffe.

Wird die Code-Implementierung oben auch als schlechte Praxis angesehen?

EDIT:

Aufgrund einiger Einschränkung auf Anwendungsumgebung bei mir läuft, wird dies mit alten Java SE 6u34.

+0

Für welche Version von Java schreiben Sie? 1.6, 1.7, 1.8, etc ... einschließlich das wird Menschen helfen, Ihre Frage zu beantworten – Kyrstellaine

Antwort

3

habe ich nicht eine neue Instanz für FileInput- Strom

Diese Aussage ist sinnlos erklären. Es gibt keine "neue Instanz". Sie haben erstellt eine neue Instanz, haben Sie einfach nicht deklariert eine Referenzvariable, um es zu speichern. Das entlastet Sie nicht von der neuen Instanz oder der Verantwortung für das Schließen.

Meine Frage ist: wird new Fileinputstream (truststore) tatsächlich Handschließ- Ja

erfordert.

oder wird es von der zugrunde liegenden Keystore-Klasse behandelt?

Nr

Schnell Blick auf den Code von Keystore.class dekompilierten zugrunde liegen, sehe ich, dass es nicht. Nur um zu bestätigen, dass dies der besondere Grund ist, warum ich die Ausnahme treffe.

"Zu viele offene Dateien": Sie verlieren Dateideskriptoren, entweder hier oder anderswo.

Wird die Code-Implementierung oben auch als schlechte Praxis angesehen?

Ja, weil Sie die FileInputStream überhaupt nicht schließen. Beachten Sie, dass das Schließen in der Zeile nach keyStore.load() nicht ausreicht, da dies eine Ausnahme auslösen könnte.

In diesen Tagen ein Try-mit-Ressourcen verwenden würde:

File truststore = new File("/keystore-sample/keystore.jks");  
try (FileInputStream fis = new FileInputStream(truststore)) 
{ 
    KeyStore keyStore = KeyStore.getInstance("JKS");  
    keyStore.load(fis, ...); 
} 

, die es auch für Sie würde automatisch schließen, wenn eine Ausnahme gibt.

+0

Vielen Dank für die Beantwortung und Korrektur meiner falschen Aussage zur neuen Objekt Instanziierung. Leider kann ich keine try-with-resources verwenden, da ich glaube, dass es nur auf Java 7+ verfügbar ist. –

1

Die Tatsache, dass Sie nicht "eine neue Instanz deklarieren" ist irrelevant - der entscheidende Punkt ist, dass Sie eine Instanz über new erstellen. Das zu verstehen, ist der Schlüssel - auch wenn Sie diese Instanz nicht verwalten, indem Sie sie einer Variablen zuweisen, haben Sie sie trotzdem erstellt.

Im Allgemeinen, wenn Sie es erstellen, liegt es in Ihrer Verantwortung, es zu schließen. Da Sie angeben, dass Sie die Try-with-Ressourcen von Java 7 nicht verwenden können, können Sie das ältere Muster zum Schließen der erstellten Ressource in einem finally-Block verwenden.

InputStream trust = null; 
try { 
    EncryptDecryptPassword crypt = new EncryptDecryptPassword(); 
    String secretKey = "secret123"; 
    String trustpassencrypted = "ecnrypted1234"; 
    String trustpass = crypt.decryptPassword(trustpassencrypted.trim(), secretKey.trim()); 

    File truststore = new File("/keystore-sample/keystore.jks");  
    KeyStore keyStore = KeyStore.getInstance("JKS");  
    trust = new FileInputStream(truststore) 
    keyStore.load(trust, trustpass.toCharArray()); 
    //Continue with the rest of the code... 
} catch (Exception e) {  
    // note that logging the stack trace is generally a better practice!  
    System.out.println("Security configuration failed with the following: " + e.getCause());   
} finally { 
    try { // because close can throw an exception 
     if (trust != null) trust.close(); 
    } catch (IOException ignored) {} 
} 

Darüber hinaus, da Sie die gleiche Sache mit allen Ausnahmen zu tun sind, ist der einzige Grund, sie alle ist, wenn Sie das Gefühl, dass es um die Lesbarkeit des Codes hinzufügt (persönlich, ich weiß nicht) indem Sie explizit angeben, welche Exceptions Sie erwarten. Alternativ können Sie wiederum, je nachdem, welche Version von Java Sie verwenden, alle im Fangblock auflisten, getrennt durch |.

+0

Danke für Ihre Antwort und Vorschlag. Ja, es ist eine Gewohnheit für mich, eine Ausnahme aufzulisten, die ich erwartet, um spezifische Aktionen dafür zu fangen und durchzuführen. –

+0

@CharlieKee Ich stimme Ihrer Angewohnheit zu, aber einige dieser Ausnahmen erweitern "GeneralSecurityException": Sie müssen sie nicht alle separat abfangen, es sei denn, Sie müssen sie wirklich alle separat aufzeichnen, was nicht wahrscheinlich ist. – EJP

Verwandte Themen