我有三个问题。
为了解释,我正在查看某人的代码,并注意到BufferedReader
有时没有关闭。通常,Eclipse会警告您这是潜在的内存泄漏(我已修复)。但是,在Callable内部类中,没有警告。
class outerClass {
...
public void someMethod() {
Future<Integer> future = outputThreadPool.submit(new innerClass(this.myProcess.getInputStream(), threadName));
...
}
class innerClass implements Callable<Integer> {
private final InputStream stream;
private final String prepend;
innerClass(InputStream stream, String prepend) {
this.stream = stream;
this.prepend = prepend;
}
@Override
public Integer call() {
BufferedReader stdOut = new BufferedReader(new InputStreamReader(stream));
String output = null;
try {
while ((output = stdOut.readLine()) != null) {
log.info("[" + prepend + "] " + output);
}
} catch (IOException ignore) {
// I have no idea why we're ignoring this... :-|
}
return 0;
}
}
}
编写代码的人都是经验丰富的Java开发人员,所以我首先想到的是它是故意的…但是可能是他们在编写代码时只是匆忙而忽略了它。
我的问题是:
Eclipse为什么不突出显示这一点(可以通过以下问题的答案来回答)?
如果在call()方法中将其关闭,可能发生的最坏情况是什么?(我想不出一个很好的理由…并且我已经搜索了一段时间…但是也许是有意不关闭BufferedReader的原因)
如果在内部类中 未 关闭BufferedReader,可能发生的最坏情况是什么?
我要说的是,由于他们正在BufferedReader
围绕给定对象创建InputStream
代码,因此可以安全地不调用该代码close()
。调用的代码close()
应该始终是创建流并使用try
/ finally完成的代码。
public static void read(String str) throws IOException {
FileInputStream stream = null
try {
stream = new FileInputStream(str);
readStreamToConsole(stream);
} finally {
if (stream != null)
stream.close();
}
}
private static void readStreamToConsole(InputStream stream) {
BufferedReader stdOut = new BufferedReader(new InputStreamReader(stream));
String output = null;
while ((output = stdOut.readLine()) != null)
System.out.println(output);
}
另一个注意事项:您的代码似乎正在记录其他进程的输出。无论如何,您可能无法关闭流。如果不自己测试,我不确定如果关闭另一个进程的流会发生什么。
哦,这IOException
不太可能发生,因为流来自另一个进程。除非发生一些不可恢复的错误,否则这不太可能发生。但是,以某种方式记录异常仍然不是一个坏主意。
编辑以解决您对混合答案的评论:
让我们使用输出流,BufferedWriter
这次以一个示例为例:
private static final String NEWLINE = System.getProperty("line.separator");
public static void main(String[] args) throws IOException {
String file = "foo/bar.txt";
FileOutputStream stream = null;
try {
stream = new FileOutputStream(file);
writeLine(stream, "Line 1");
writeLine(stream, "Line 2");
} finally {
if (stream != null)
stream.close();
}
}
private static void writeLine(OutputStream stream, String line) throws IOException {
BufferedWriter writer = new BufferedWriter(new InputStreamWriter(stream));
writer.write(line + NEWLINE);
}
这可行。writeLine方法用作创建writer
单个line
文件并将其实际写入文件的委托。当然,这种逻辑可能更复杂,例如将一个对象变成a
String
并将其写入。这也使该main
方法更易于阅读。
现在,如果相反,我们关闭了BufferedWriter呢?
private static void writeLine(OutputStream stream, String line) throws IOException {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new InputStreamWriter(stream));
writer.write(line + NEWLINE);
} finally {
if (writer != null)
writer.close();
}
}
尝试以此运行它,它将在每次第二次writeLine
调用时失败。最好始终在创建流的地方而不是在传递流的地方关闭流。最初可能没问题,但是随后尝试更改该代码可能会导致错误。如果我只writeLine
使用坏方法进行了一次调用,而其他人想添加第二个调用,那么他们将不得不重构代码,以致writeLine
始终无法关闭流。变得近距离开心可能会引起头痛。
还要注意,从技术上讲,BufferedWriter
is不是系统资源的实际句柄,FileOutputStream
而是is,因此无论如何,您都应该关闭实际资源。
因此,经验法则:仅在创建流的地方关闭流,并始终在try / finally块(或Java 7很棒的try /
resource块
,为您关闭)中进行创建和关闭。
假设我有一个普通的应用程序,其中我正在使用ApplicationContext ApplicationContext=new FileSystemXmlApplicationContext(“bean.xml”)创建一个Spring应用程序上下文 现在,假设在这个bean.xml有Spring bean的bean定义,所以当我创建应用程序上下文时,Spring容器将为这个实例化和初始化一个对象。
如果在java中执行关闭挂钩期间引发了未捕获的异常,jvm是否会立即退出,而不运行其余已注册的关闭挂钩(如果有)?从javadocs: 未捕获的异常通过调用线程ThreadGroup对象的uncaughtException方法在关闭钩子中处理,就像在任何其他线程中一样。此方法的默认实现将异常的堆栈跟踪打印到System.err并终止线程;它不会导致虚拟机退出或停止。 似乎其他关机挂钩应该运行...
问题内容: 我有一个使用简单套接字在两个系统之间传递某些字符的应用程序。我的Java应用程序作为服务器运行。我建立了良好的连接,甚至传递了一条消息。但是,发送完一条消息后,我的连接关闭。 从我可以看出来的好像是在关闭时,套接字本身正在关闭吗?!这很不好,因为我有多个要在同一连接上发送的消息。 我吃饱了吗?如何在Java中维护此连接? 问题答案: 是的,关闭任何作家/读者将关闭他们包装的所有其他作家
问题内容: 我注意到,如果关闭,我将无法再从键盘插入输入,因为已经关闭了。无论如何,我可以保留(删除文件时需要它),然后从键盘添加更多输入吗? 问题答案: 看起来您需要: http://commons.apache.org/io/apidocs/org/apache/commons/io/input/CloseShieldInputStream.html 在制作读者之前,先将System.in环绕
相关问题,但不是我想知道的,因为我对PHPlib/函数的具体行为很好奇: 当连接在事务中间关闭时会发生什么? 当连接关闭时,未提交的事务会发生什么? 假设我有这样的代码(不管它是好的还是坏的实践): 包含提交和回滚的将被跳过,而连接将在事务启动后但在调用提交或回滚之前关闭。 该事务是否也会立即被销毁/结束/不管什么专有名词,或者它会保留下来并可能阻止来自其他服务的其他查询?
编辑问题,以包括所需的行为、特定问题或错误,以及重现问题所需的最短代码。这将帮助其他人回答这个问题。 我们知道:load with memory_order_acquire,store with memory_order_release但是,我发现用gcc4.8.2,open -O2时,抛出了一个编译错误,/usr/include/c/4 . 8 . 2/atomic:199:9:error:对于