I have the following code:
public void disconnect()
{
running = false;
if(thread != null)
thread.interrupt();
thread = null;
try
{
socket.close();
}catch(Exception e){e.printStackTrace();}
}
I have a BufferedReader that collects the input from the stream and a PrintWriter that sends messages through the output stream. Should the BufferedReader and the PrintWriter be closed before i close the socket? Is it bad to leave the i/o streams open?
According to the Java Networking Tutorial
"You should close any streams connected to a socket before you close the socket itself."
You must close the output stream, so it gets flushed. That closes both the socket and the input stream. Closing any one of those closes the other two. You don't need to close the input stream at all. Strictly speaking for safety's sake you should probably also close the socket itself in a finally block.
If you don't close the BufferedWriter, you might lose some buffered but un-flushed data.
There's also a school of thought that says you shouldn't use PrintWriter, or to be careful if you do, because it swallows IOExceptions.
Every stream you open uses OS resources. When you call close on a stream it is marked for Garbage Collection and the memory is freed after GC. If you don't close the stream, it will be closed by GC (http://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html#close%28%29) but it's not clear at all, when GC will hit that object.
So it's always better to close a stream to instantly free memory.
Related
I just want to clear a doubt that I've been harboring for quite some time now: Is it possible for sockets in Java to be closed even if the .close() method hasn't been called in the code?
Yes. Closing either the input or the output stream of the socket closes the other stream and the socket.
This code below is in java.net.AbstractPlainSocketImpl
/**
* Cleans up if the user forgets to close it.
*/
protected void finalize() throws IOException {
close();
}
finalize() gets called when the garbage collector is run. So if you lose all references to your Socket, it will be closed. You shouldn't do this though, as it's bad practice - you never know when the garbage collector will run, so the socket could stay open for awhile. I don't really know if this counts as it does call close() underneath. Closing input, and output streams are different that the socket. I don't think they really count.
I have 'n' server threads, and each one listen to 1 client.
When a server thread receives a message from its client, it needs to notify the other 'n-1' clients, and that's the reason why I keep a shared object (containing an array of 'n' sockets, one for each client) between the server threads.
Moreover, in the main server thread that holds the ServerSocket, every time I accept a new connection with a client I open a BufferedWriter/Reader to give a first answer to him using the new socket returned from ServerSocket.accept().
In case of an "OK" answer I open a new thread passing the new socket to it, in order to listen to the new client's following requests.
The problem is that i cannot close the BufferedReader and the BufferedWriter in the main server thread, because it will also close the underlying stream, causing problems to the server thread that is listening to that socket/stream.
And the question: if I open another BufferedReader (bound to the same socket) in the new thread, and then close it, will other BufferedReaders(Writers) ( specifically the ones opened in the main server thread, that i couldn't close before ) opened on the same socket be closed? Will an exception be thrown on them?
It could be possible to share the opened BufferedReader / Writer instead of the socket, to avoid instantiating every time a new object, but this is a question related to what could happen if i do things in the way described above.
Please tell me if I hadn't been clear, my english is not really good.
Closing any Reader or Writer or stream wrapped around a stream closes the wrapped stream.
Closing either the input stream or the output stream of a socket closes the other stream and the socket.
Closing the socket closes both streams.
In other words closing any of it closes all of it.
As noted in comments, multiple buffered streams/Readers/Writers wrapped around a single stream cannot work.
Multiple threads reading from/writing to the same socket is unlikely to work correctly either, unless you take great care with synchronization and buffering.
You should not do any I/O with an accepted socket in the accept loop. Otherwise you can block, which affects further clients.
You need to rethink your design.
Each Socket with an open connection to another Socket has an open InputStream and an open OutputStream. Closing either one of these streams will also close the socket. Closing a socket or its streams will not affect other sockets unless they are connected. You don't want to close any streams unless you also want to close the connection between the sockets using the streams. Please ask if there is something i missed or if you have other questions :)
I am working in a legacy java application, In many files, socket and streams are used, where sockets are getting closed but not the streams, is this necessary to close all the streams before closing the socket. because I am getting "too many open files error", is this error because of not closing the streams.....
closing the socket will automatically close the streams also?
From the Socket Javadoc:
Closing this socket will also close the socket's InputStream and OutputStream.
So generally speaking, closing the socket should be enough to close both streams it created.
Your "too many open files error" is most likely caused by something else.
Closing any one of those closes the other two, but you should close the outermost output stream (or Writer) that you have wrapped around the socket. That closes the input stream and the socket. If you don't close the outermost output stream yourself, it won't get flushed, and so you can lose data if there is a buffered outpput stream or writer in the stack. You could also close the socket itself in a finally block to be sure: in fact lack of finally blocks may well be the cause of your problem.
I was wondering that what is the best/appropriate way to release file resources/handles.
Traditional code,
BufferredInputStream stream = null
try{
----
stream = new BufferredInputStream(new FileInputStream());
----
} finally{
if(stream != null){
stream.close()
}
}
Will the file handle be released by closing BufferredInputStream.close alone or it needs the underlying stream(i.e. FileInputStream.close()) also to be called explicitly.
P.S. Javadoc for [FilterOutputStream.close] method specifies that it will explicitly close the underlying stream too. But other streams doesn't seem to have this in the doc.
[FilterOutputStream.close]: http://docs.oracle.com/javase/1.4.2/docs/api/java/io/FilterOutputStream.html#close%28%29
Please advice. Thanks in advance.
You can always check the source code for the underlying class to determine the exact behavior.
However, in this case calling close() on BufferedInputStream will also close the underlying stream i.e. FileInputStream.
The source code is available here
Your approach is correct. When in doubt, always check the source code. http://www.docjar.com/html/api/java/io/BufferedInputStream.java.html the close method is closing "in" which was chained to BufferedInputStream.
When multiple streams are chained closing the stream that was last to be constructed will close the underlying stream. So, closing BufferedInputStream will also close the underlying FileInputStream.
So you just call close() on one stream and it will automatically close the underlying stream.
BufferredInputStream doesn't itself hold any system resources so BufferredInputStream.close() will simple propagate the close call to InputStream it wraps.. so it should do just fine.
I could not find clarification of this in the documentation.
But when we have a Process object and call getInputStream(),
Do we get a new stream that we should explicitly close when we are done with it?
or
do we get the stream that is already there, associated with the Process, that we should not close, but the Process would take care of closing it?
Basically, how should we interact with the stream we get from Process.getInputStream()? close or not to close?
From reading UNIXProcess.java, this is what happens:
We need to distinguish between two states: either process is still alive, or it is dead.
If the process is alive, by closing OutputStream (goes to stdin of the process), you are telling the process that there is no more input for it. By closing InputStreams (stdout, stderr of the process), process is no longer to write to these (it will get SIGPIPE if it tries).
When process dies, Java will buffer remaining data from stdout/stderr, and close all three streams for you (it is running "process reaper" thread, which is notified on process death). Any attempt to write to OutputStream will fail. Reading from InputStream will return buffered data, if any. Closing any of them has no benefit, but also causes no harm. (Underlying file descriptors are closed by this time).
My first reactions was to close it, you always close streams that you open. I do realize the documentation is not up to par, but since they don't explicitly state do not close that to me means follow good programming practices.
InputStream is = process.getInputStream()
try {
// your code
} finally {
try { is.close(); } catch (Exception ignore) {}
}
If you need to make sure this isn't problematic, just write a quick test case where you great from the input stream a few dozen times, each time opening and closing the InputStream.
When you call Process.getInputStream() you get an existing input stream that was set up for the process. When the process dies, that input stream does not go away automatically - think of it as a buffer that you can still read from. The process's end of the pipe might be closed, but your end is not. It is your responsibility to close it, though GC will eventually get it.
You should also close the other two: getErrorStream() and getOutputStream().
You do not close streams, that you did not open - that's a nasty side effect.
If you created the process, kill it first and close streams after that.
I always close them! I am not 100% sure, but as far as I know if you leave the inputstream open, the file will be open until you close it!! So follow the "standard rules" and close it! follow an example:
Process Builder waitFor() issue and Open file limitations