Some tool I have uses Writer as output. I want to write to System.out, so I created an OutputStreamWriter for System.out. My problem is that I want to do other things with the standard output of my program after I completed this task. I did not find any means to detach the writer.
Is there any common Writer implementation that can do that? Should I write my own Writer? Should I call flush() on my OutputStreamWriter and then leak it?
You can override close and flush instead:
PrintWriter w = new PrintWriter(System.out) {
#Override
public void close() {
flush();
}
};
Yes, just .flush() it and let it be. It doesn't mean you'd "leak" it: the Writer object will get garbage collected, and the underlying stream is still in use. Nothing wrong with that.
Related
The InputStream is passed as a parameter from somewhere, where it will be further processed and then closed. So I don't want to close the InputStream here. Consider the following code:
void readInputStream(final InputStream inputStream) {
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = bufferedReader.readLine() != null) {
// do my thing
}
}
If I close the BufferedReader and/or the InputStreamReader, then the underlying InputStream will be closed as well, according to another Stackoverflow post.
My question: Do Readers need to be closed, even if the underlying InputStream is closed somewhere else? Can I get a memory leak by not closing Readers?
Do readers need to be closed, even if the underlying InputStream is closed somewhere else?
No they absolutely don't need to be in that scenario. But it is generally a good idea to close them anyway.
Can I get a memory leak by not closing readers?
No, there is no memory leak, assuming that the Reader itself becomes unreachable once you have finished with it. And besides, a Reader doesn't typically use a lot of memory.
The more important question is whether you can get a resource leak by not closing a Reader. The answer is ... it depends.
If you can guarantee that the underlying InputStream will always be closed somewhere else in the application, then that takes care of possible memory leaks.
If you can't guarantee that, then there is a risk of a resource leak. The underlying OS level file descriptors are a limited resource in (for example) Linux. If a JVM doesn't close them, they can run out and a certain system calls will start to fail unexpectedly.
But if you do close the Reader then the underlying InputStream will be closed.
Calling close() more than once on a InputStream is harmless, and costs almost nothing.
The only case where you shouldn't close the Reader is when it would be wrong to close the underlying InputStream. For example, if you close a SocketInputStream the rest of the application may not be able to reestablish the network connection. Likewise, the InputStream associated with System.in usually cannot be reopened.
In that case, it is actually safe to allow the Reader you create in your method to be garbage collected. Unlike InputStream, a typical Reader class doesn't override Object::finalize() to close its source of data.
#Pshemo brought up an important point about system design.
If you are accepting an InputStream as an argument, then it may be wrong to wrap it with a local Reader ... especially a BufferedReader. A BufferedReader is liable to read-ahead on the stream. If the stream is going to be used by the caller after your method returns, then any data that has been read into the buffer but not consumed by this method is liable to be lost.
A better idea would be for the caller to pass a Reader. Alternatively, this method should be documented as taking ownership of the InputStream. And in that case, it should always close() it.
Yes, Readers need to be closed. Use a proxy, e.g. CloseShieldInputStream, to prevent the passed parameter from being closed.
void readInputStream(InputStream inputStream) throws IOException{
try (var bufferedReader = new BufferedReader(new InputStreamReader(
new CloseShieldInputStream(inputStream)))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
// do my thing
}
}
}
JIC: Similar to the input shield, Apache Commons I/O also provides an output shield to solve the similar problem with closing a wrapping output stream, - CloseShieldOutputStream
For more detailed considerations, please refer to the original answer. Credits to #stephen-c
When I saw descriptions about these two methods as below, I felt a bit confused about them.
protected void drain(): Similar to flush but does not propagate the flush to the underlying stream.
void flush(): Writes any buffered output bytes and flush through to the underlying stream.
For example:
FileOutputStream out = new FileOutputStream("test.txt");
ObjectOutputStream oout = new ObjectOutputStream(out);
Question 1:
If I call oout.flush(), it will force the output data in the ObjectOutputStream to be written to the underlying FileOutputStream, but it doesn't guarantee that these data will be subsequently written from FileOutputStream to the file "test.txt" in the disk since I don't call out.flush(), is this correct?
Question 2:
What if I call oout.drain()?
What executions will be done?
Question 1:
If I call oout.flush(), it will force the output data in the ObjectOutputStream to be written to the underlying FileOutputStream, but it doesn't guarantee that these data will be subsequently written from FileOutputStream to the file "test.txt" in the disk since I don't call out.flush(), am I right?
No, you are wrong. It does flush the FileOutputStream. However, as FileOutputStream doesn't buffer or flush, in fact there is no difference between drain() and flush() in this circumstance. If there had been a BufferedOutputStream around the FileOutputStream, there would have been a difference.
Question 2:
What if I call oout.drain()? What executions will be done?
It will flush the ObjectOutputStream but not the underlying stream, exactly as it says in the Javadoc.
You have somehow managed to get this completely back to front. I can't understand how: the Javadoc is quite clear. Also, as drain() is protected it is none of your business anyway.
Flush will write the data to the test.txt. However, drain is similar to flush but does not propagate the flush to the underlying stream.
I am using Java 1.6.
I am facing some memory heap issues and in the heap dump I can see that ObjectOutputStream objects are consuming more memory.
In my application at some places, I have used ObjectOutputStream but missed to close the stream in some of the methods.
So will this impact the performance ??
Will the stream remain open and will it consume Heap Memory ??
Will Java close the stream when the method is finished where ObjectOutputStream is used but stream is not closed ??
No, java will not close the stream all by itself.
How badly leaving it open will affect your performance depends on the rest of the code. If the method is often, it will be a serious problem. Regardless of that, it's just way better practice to close your streams.
It's a great reason to upgrade to java 7, where you can write
try (ObjectOutputStream stream = ...) {
...
}
Here java will close the stream for you when you're done with it, no matter how that happens.
Off course you can achieve the same behaviour in java 6 but it's more work.
In Java 1.6, looking at the docs :
close
public void close()
throws IOException Closes the stream. This method must be called to release any resources associated with the stream.
must is pretty strong, so I would say that yes, you must call it.
We can have a look at the source :
public void close() throws IOException {
flush();
clear();
bout.close();
}
It does clean a few things. It also implements the interface AutoCloseable, which :
public interface AutoCloseable
A resource that must be closed when it is no longer needed.
So, call the close() method.
Note : Even if close() did nothing I would still call it to give a clear indication in the code that this is not to be used anymore, but that's probably a personal preference.
Adding some comments to Stef's great answer:
From another point of view, you may ask yourself: what is the reason for leaving the ObjectOutputStream open in some cases? If you don't use it anymore, then you should definitely close it as soon as possible. It is a good idea to follow this convention.
The close method makes sure that there are no references to the stream so the resources can be garbage collected; using it is definitely something you want to do in order to have a healthy memory space.
What I am usually doing is having a try {} finally {} without a catch {}:
public static void closeStream(OutputStream out)
{
if (out != null) out.close();
}
...
ObjectOutputStream out = null;
try
{
//do something
}
finally
{
closeStream(out);
}
You can of course use a catch block if you need to, or add throws to your method. Either way, this way you can be sure that stream resources are released.
Hi I need a answer for necessity of flush in I/O streams in java.since in my program with flush and without flush the output is same.ie,every thing is written in to the destination file.then why i need flush?will file input stream consumes buffer memory?
the below is my simple sample program
file = new File("c:/newfile.txt");
fop = new FileOutputStream("c:/newfile.txt");
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
// get the content in bytes
byte[] contentInBytes = content.getBytes();
fop.write(contentInBytes);
fop.flush();
fop.close();
even when i command flush and close it can write the contents in to the file properly..?then y we need flush?and will file outputstream consumes memory?
Close calls flush on the stream, so flush is not needed if you want to close the stream.
Flush is useful if you want to make sure that the data is saved, without closing a stream, e.g. when sending messages over the Internet, or writing to the console. You may notice, that if you write to console with system.out.print(), then the output is not displayed, until you call flush, or until there is a new line in the text (in which case Java will call flush for you).
See more on this question
In fact, FileOutputStream is not buffered, so the data is directly written to the file.
The abstract OutputStream defines flush (an empty method) to accomodate also the needs of buffered streams, so FileOutputStream inherits it.
If you are not certain of the underlying implementation, it is generally good practice to flush the streams before closing them.
Also, in your code there is a little error:
file = new File("c:/newfile.txt");
fop = new FileOutputStream("c:/newfile.txt");
// Will never happen, new FileOutputStream creates the file
if (!file.exists()) {
file.createNewFile();
}
EDIT:
As for the close part of the question:
When you comment out close(), then exiting main() the close method is called by the finalizer (i.e before the stream is garbage collected, a JVM thread calls its finalize() method, which in turn calls the close() method), but you can't sensibly rely on the finalizer: you don't own it and you can't be sure of when it is activated.
Again , best practice is to call close() explicitly.
Short question,
I saw in some old code where a ByteArrayInputStream was created like:
new BufferedReader(new InputStreamReader(new ByteArrayInputStream(somebytes)));
And then the BufferedReader is used to read out somebytes line by line.
All working fine, but I noticed that the BufferedReader is never closed.
This is all working in a long running websphere application, the somebytes are not terrible big (200k most), it is only invoked a few times a week and we're not experiencing any apparent memory leaks. So I expect that all the objects are successfully garbage collected.
I always (once) learned that input/output streams need to be closed, in a finally statement. Are ByteStreams the exception to this rule?
kind regards
Jeroen.
You don't have to close ByteArrayInputStream, the moment it is not referenced by any variable, garbage collector will release the stream and somebytes (of course assuming they aren't referenced somewhere else).
However it is always a good practice to close every stream, in fact, maybe the implementation creating the stream will change in the future and instead of raw bytes you'll be reading file? Also static code analyzing tools like PMD or FindBugs (see comments) will most likely complain.
If you are bored with closing the stream and being forced to handle impossible IOException, you might use IOUtils:
IOUtils.closeQuietly(stream);
It is always good practice to close your readers. However not closing a ByteArrayInputStream does not have as heavy of a potential negative effect because you are not accessing a file, just a byte array in memory.
As #TomaszNurkiewicz mentioned it's always good to close the opened stream. Another good way to let it do the try block itself. Use try with resource like.......
try ( InputStream inputStream = new ByteArrayInputStream(bytes); Workbook workBook = new XSSFWorkbook(inputStream)) {
here Workbook and InputStream both implements Closeable Interface so once try block completes ( normally or abruptly), stream will be closed for sure.
Resources need to be closed in a finally (or equivalent). But where you just have some bytes, no it doesn't matter. Although when writing, be careful to flush in the happy case.