CipherInputStream解密出错时不会自动关闭底层流,必须主动释放;推荐用try-with-resources确保无论成功或抛BadPaddingException等异常均自动关闭;若手动关闭,须在finally中判空并处理IOException;Cipher.init()失败后创建的实例仍需关闭,不可因未读数据而忽略。

CipherInputStream解密出错时不会自动关闭底层流,必须主动释放,否则容易造成文件句柄泄漏、网络连接挂起等资源问题。关键不是“有没有读到数据”,而是“只要实例化了,就持有了底层流的引用”。
用try-with-resources最稳妥
这是首选方案,能确保无论解密是否成功、抛出BadPaddingException还是IllegalBlockSizeException,JVM都会自动调用close()释放资源:
- 把CipherInputStream和它包装的原始流(如FileInputStream)都声明在try括号里
- 底层流必须实现AutoCloseable(标准IO流都满足)
- 无需额外catch或finally,语法本身保障清理
手动关闭必须进finally块
如果因兼容性或逻辑限制不能用try-with-resources,务必把close()放在finally中,并做空值判断:
- 变量声明在try外,初始化在try内,确保异常发生后仍可访问
- 关闭前先判null,避免NullPointerException
- 捕获IOException并忽略或记录日志,防止掩盖原始解密异常
别忽略Cipher初始化失败的场景
Cipher.init()失败(比如InvalidKeyException)可能导致CipherInputStream构造成功但首次read()就抛异常。此时流对象已创建,仍需关闭:
立即学习“Java免费学习笔记(深入)”;
- 不能认为“还没开始读就不需要关”
- 若在catch中提前赋值了cis,应在catch末尾也调用close()
- 重写close()方法的子类除外,但官方CipherInputStream默认会委托到底层流
常见错误做法要避开
这些写法看似合理,实际容易漏关流:
- 只在try末尾close():异常一抛就跳过,根本执行不到
- 只在catch里close():遇到OutOfMemoryError这类Error,catch可能不触发
- 关闭CipherInputStream却没关原始流:虽然默认会关,但依赖未重写的实现,不够保险


















