Are the following try-with blocks similar? Will the dataSocket.getOutputStream() be closed in both cases?
a)
try (Socket dataSocket = new Socket(...);
OutputStream socketStream = dataSocket.getOutputStream();
BufferedOutputStream outputStream = new BufferedOutputStream(socketStream)
) {.....}
b)
try (Socket dataSocket = new Socket(...);
BufferedOutputStream outputStream = new BufferedOutputStream(dataSocket.getOutputStream())
) {.....}
Note. in b) there is no explicit variable for dataSocket.getOutputStream(), in a) we have socketStream.
According to BufferedOutputStream JavaDoc,
Closes this output stream and releases any system resources associated with the stream.
Closing outputStream would close the underlying outputstream. This is also proven in the source code of BufferedOutputStream's close() method.
public void close() throws IOException {
try {
flush();
} catch (IOException ignored) {
}
out.close();
}
Yes, it will be closed in both cases. Even using only Socket sentence, they should be closed. When socket is closed, streams are closed. Anyway, I prefer explicity add Streams declaration on try-with structure.
Related
The following question I have is pretty straightforward.
Here is my code:
public class Protocol implements Runnable {
private SSLSocket socket = null;
private InputStream is = null;
private OutputStream os = null;
...
public Protocol(Socket s) {
socket = (SSLSocket)s;
is = socket.getInputStream();
os = socket.getOutputStream();
}
#Override
public void run() {
...
ping();
socket.close();
...
}
public void ping() {
BufferedWriter writer;
try {
writer = new BufferedWriter(new OutputStreamWriter(os));
writer.write("OK");
}
catch (IOException e) { System.out.println("ERROR: " + e.getLocalizedMessage()); }
finally { writer = null; }
}
I understand I didn't include a lot of source code, but this should be enough to answer the question. As you can see, in the "ping" method I have a BufferedWriter which I create to write an "OK" string to the remote source. Later on, I close the Socket.
So my simple question is this - From what I understand, since I close the socket, the chain should go like this:
Close socket ----> which closes is and os ----> closes writer
So, by closing the Socket, I am also closing and allowing the BufferedWriter to be freed by the GC. Am I understanding this correctly or doing something wrong? Is this true for all writers and readers that I initialize in other methods (i.e. BufferedInputStream). And by setting these variables null at the end of the method, am I helping the GC to distinguish between what should be freed? Or should I not do this?
Thanks!
From what I understand, since I close the socket, the chain should go like this:
Close socket ----> which closes is and os ----> closes writer
No. The BufferedWriter is wrapped around the socket output stream, but the socket doesn't know that. It has no way of closing it.
So, by closing the Socket, I am also closing and allowing the BufferedWriter to be freed by the GC.
No and no. The BufferedWriter is available for GC as soon as ping() returns, and it is never closed at all.
Am I understanding this correctly
No.
or doing something wrong?
Yes. You shouldn't create a new BufferedWriter per message. You should use the same one for the life of the socket, and close it instead of the socket. Similarly you should only use one input stream or Reader for the life of the socket. Otherwise you can lose data in their buffers.
Is this true for all writers and readers that I initialize in other methods (i.e. BufferedInputStream).
No.
And by setting these variables null at the end of the method, am I helping the GC to distinguish between what should be freed?
No. You are just wasting time and space. The method is about to exit anyway, so all its local variables disappear.
Or should I not do this?
You should not do any of it.
I know that the resource you pass with a try, will be closed automatically if the resource has AutoCloseable implemented. So far so good. But what do I do when i have several resources that I want automatically closed. Example with sockets;
try (Socket socket = new Socket()) {
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
}
So I know the socket will be closed properly, because it's passed as a parameter in the try, but how should the input and output be closed properly?
Try with resources can be used with multiple resources by declaring them all in the parenthesis. See the documentation
Relevant code excerpt from the linked documentation:
public static void writeToFileZipFileContents(String zipFileName,
String outputFileName)
throws java.io.IOException {
java.nio.charset.Charset charset =
java.nio.charset.StandardCharsets.US_ASCII;
java.nio.file.Path outputFilePath =
java.nio.file.Paths.get(outputFileName);
// Open zip file and create output file with
// try-with-resources statement
try (
java.util.zip.ZipFile zf =
new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer =
java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
// Enumerate each entry
for (java.util.Enumeration entries =
zf.entries(); entries.hasMoreElements();) {
// Get the entry name and write it to the output file
String newLine = System.getProperty("line.separator");
String zipEntryName =
((java.util.zip.ZipEntry)entries.nextElement()).getName()
newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
}
If your objects don't implement AutoClosable (DataInputStream does), or must be declared before the try-with-resources, then the appropriate place to close them is in a finally block, also mentioned in the linked documentation.
Don't worry, things will "just work". From Socket's documentation:
Closing this socket will also close the socket's InputStream and OutputStream.
I understand your concern about not explicitly calling close() on the input and output objects and in fact it's generally better to ensure all resources are automatically managed by the try-with-resources block, like this:
try (Socket socket = new Socket();
InputStream input = new DataInputStream(socket.getInputStream());
OutputStream output = new DataOutputStream(socket.getOutputStream());) {
} catch (IOException e) {
}
This would have the effect that the socket object would be "closed multiple times", but that should not do any harm (this is one of the reasons why it's generally advised that all implementations of close() be made idempotent).
In addition to the above answers, This is the improvement added in Java 9.
Java 9 try-with-resources makes an improved way of writing code. Now you can declare the variable outside the try block and use them inside try block directly.because of this you will get following benefits.
The Resources which it declared outside try( which is effectively final or final) can be automatically close by automatic resource management by just adding them in the try block.
You no need to re-refer objects declared outside try block nor need to close them manually as we need to do in Java 7.
It also helps to write clean code.
try-with-resource can we write like this in Java 9.
public void loadDataFromDB() throws SQLException {
Connection dbCon = DriverManager.getConnection("url", "user", "password");
try (dbCon; ResultSet rs = dbCon.createStatement().executeQuery("select * from emp")) {
while (rs.next()) {
System.out.println("In loadDataFromDB() =====>>>>>>>>>>>> " + rs.getString(1));
}
} catch (SQLException e) {
System.out.println("Exception occurs while reading the data from DB ->" + e.getMessage());
}
}
Here automatic resource management will automatically close both the objects dbCon & rs.
For the better understanding of the list of above define use cases please find some Java 7 code.
Example 1:
public void loadDataFromDB() throws SQLException {
Connection dbCon = DriverManager.getConnection("url", "user", "password");
try (ResultSet rs = dbCon.createStatement().executeQuery("select * from emp")) {
while (rs.next()) {
System.out.println("In loadDataFromDB() =====>>>>>>>>>>>> " + rs.getString(1));
}
} catch (SQLException e) {
System.out.println("Exception occurs while reading the data from DB ->" + e.getMessage());
} finally {
if (null != dbCon)
dbCon.close();
}
}
Example 2:
// BufferedReader is declared outside try() block
BufferedReader br = new BufferedReader(new FileReader("C://readfile/input.txt"));
try (BufferedReader inBr = br) {
// ...
}
} catch (IOException e) {
// ...
}
In the above samples you can see if the object is ouside try then either we need to close manually or re-refer it. Also in the case of multiple objects in the try block, it looks messy and even if you declared inside try then you can't use outside try block.
Answers above are great but there are some cases when try-with-resources doesn't help.
Take a look at this code example:
private static byte[] getFileBytes(Collection<String> fileContent) throws CustomServiceException {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(baos))) {
for (String fileLine : fileContent) {
writer.append(fileLine);
writer.newLine();
}
}
return baos.toByteArray();
} catch (IOException e) {
throw new CustomServiceException(SC_INTERNAL_SERVER_ERROR, "Unable to serialize file data.");
}
}
In this example u can't just use try-with-resources block cause writer has to flush the output buffer to the underlying character stream so placing writer into try-with-resources block won't do the trick and method will return empty array.
I know that to close all the internal and enclosing streams you can close the outermost Stream and it will take care of the enclosing Streams but do it waits to read and write data completely before closing the internal streams or just perform the required operations.
I just want to figure out what happens and how internal functions are called on the inner streams when we close an enclosing Stream? Just like in the below code
public static void serialize(Object obj, String fileName)
throws IOException {
FileOutputStream fos = new FileOutputStream(fileName);
BufferedOutputStream bos = new BufferedOutputStream(fos);
ObjectOutputStream oos = new ObjectOutputStream(bos);
bos.flush();
oos.writeObject(obj);
oos.close();
}
When I close the Object Stream will it wait for File Stream to perform its function?
Yes, if you close the ObjectOutputStream, all pending write operations will be performed.
That is because ObjectOutputStream calls innerStream.flush() wenn you call close() on it.
And BufferedOutputStream also calls innerStream.flush() in its own flush method.
All buffering stream classes I know do so.
This question already has answers here:
Closing inputstreams in Java
(6 answers)
Closed 3 years ago.
InputStream in = SomeClass.getInputStream(...);
BufferedInputStream bis = new BufferedInputStream(in);
try {
// read data from bis
} finally {
bis.close();
in.close();
}
The javadoc for BufferedInputStream.close() doesn't mention whether or not the underlying stream is closed:
Closes this input stream and releases any system resources associated
with the stream. Once the stream has been closed, further read(),
available(), reset(), or skip() invocations will throw an IOException.
Closing a previously closed stream has no effect.
Is the explicit call to in.close() necessary, or should it be closed by the call to bis.close()?
From the source code of BufferedInputStream :
public void close() throws IOException {
byte[] buffer;
while ( (buffer = buf) != null) {
if (bufUpdater.compareAndSet(this, buffer, null)) {
InputStream input = in;
in = null;
if (input != null)
input.close();
return;
}
// Else retry in case a new buf was CASed in fill()
}
}
So the answer would be : YES
BufferedInputStream doesn't hold any system resources itself; it simply wraps around an InputStream which holds those resources. Therefore the BufferedInputStream forwards the close operation onto the wrapped InputStream which will then release its resources.
When you close a BufferedInputStream, the underlying InputStream is indeed also closed. :)
Yes. The underlying stream will be closed.
Here is the Java implementation
/**
* Closes this input stream and releases any system resources
* associated with the stream.
* Once the stream has been closed, further read(), available(), reset(),
* or skip() invocations will throw an IOException.
* Closing a previously closed stream has no effect.
*
* #exception IOException if an I/O error occurs.
*/
public void close() throws IOException {
byte[] buffer;
while ( (buffer = buf) != null) {
if (bufUpdater.compareAndSet(this, buffer, null)) {
InputStream input = in;
in = null;
if (input != null)
input.close();
return;
}
// Else retry in case a new buf was CASed in fill()
}
}
So, the stream will be closed
I'am trying to write the inputstream image to OutputStream to display the image in the browser this is the code:
try
{
InputStream input = Filer.readImage("images/test.jpg");
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1)
{
responseBody.write(buffer, 0, bytesRead);
}
}
catch(IOException e)
{
System.out.println(e);
}
the readImage:
public static InputStream readImage(String file) throws IOException {
try (InputStream input = new FileInputStream(file)) {
return input;
}
}
but I get an error while writing:
java.io.IOException: Stream Closed
any ideas?
The try-with-resources closes the stream when you exit the block
try (InputStream input = new FileInputStream(file)) {
ie. when your method returns.
Just remove it and take care of closing the stream at the end of your other method body.
As stated in the comments, here's a link to the official tutorial on try-with-resources.
Taken from oracle tutorial the resource is closed when the statement completes:
The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
Prior to Java SE 7, you can use a finally block to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. The following example uses a finally block instead of a try-with-resources statement: