2017-02-21 48 views
0

我现在面临的问题与我的应用程序之一,遇到处理大量交易是需要打开文件和阅读内容时以下异常:我需要在此代码中手动关闭FileInputStream吗?

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

我已经写在Java下面的示例代码:

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());   
} 

正如你所看到的,我没有的FileInput流声明一个新的实例,就像下面
更正:我目的是要表达我没有分配新创建的FileInputStream到一个变量和以后手动关闭它,如下所示:

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

我的问题是:将新的FileInputStream(信任)实际上需要手动关闭,否则将由底层Keystore类来处理?快速浏览Keystore.class的底层反编译代码,我没有看到。只是为了确认这是否是我触及例外的特殊原因。

此外,上面的代码实现被认为是不好的做法?

编辑:

由于对应用环境的一些限制,我运行,这是用旧的Java SE 6u34。

+0

你正在写哪个版本的Java? 1.6,1.7,1.8等...包括那将帮助人们回答你的问题 – Kyrstellaine

回答

3

我没有的FileInput流

这种说法是毫无意义的声明一个新的实例。没有“宣布新实例”这样的事情。你有创建一个新的实例,你只是没有宣布 a 参考变量存储它。这并不免除你的新实例,或关闭它的责任。

我的问题是:将新的FileInputStream(信任)实际上需要手动关闭

是。

或者它将由底层Keystore类处理?

上Keystore.class的潜在反编译的代码快速一眼,我没有看到。只是为了确认这是否是我触及例外的特殊原因。

“打开的文件太多”:你正在泄漏文件描述符,无论是在这里或其他地方。

此外,上面的代码实现被认为是不好的做法吗?

是的,因为你根本没有关闭FileInputStream。并且请注意,在keyStore.load()之后关闭它是不够的,因为这可能会引发异常。

这些日子里,你会使用try-与资源:

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

这将自动为你关闭它,即使有一个例外。

+0

感谢您回答并纠正我在新对象实例化上的错误陈述。不幸的是,我不能使用try-with-resources,因为我相信它只适用于java 7+。 –

1

事实上,你不“宣布一个新的实例”是无关紧要的 - 关键是你通过new创建一个实例。理解这一点非常重要 - 即使您没有将该实例的句柄分配给变量,也仍然创建它。

一般来说,如果你创建它,你有责任关闭它。既然你说你不能使用Java 7的try-with-resources,你可以使用在finally块中关闭已创建资源的旧模式。

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) {} 
} 

此外,因为你所有的例外做同样的事情,唯一的原因全部列出来就是,如果你觉得它增加了代码的可读性(个人而言,我不知道)通过明确你所期望的异常。或者,再次取决于您使用的Java版本,可以将它们全部列在catch块中,用|分隔。

+0

感谢您的回答和建议。对我来说,列举出我期望捕捉并执行特定动作的异常是我的习惯。 –

+0

@CharlieKee我同意你的习惯,但是其中的几个例外扩展了'GeneralSecurityException':你不需要单独捕获它们,除非你真的需要单独记录它们,这是不可能的。 – EJP