This question already has answers here:
Resource leak: 'in' is never closed
(14 answers)
Closed 2 years ago.
I'm watching some java tutorials and wondering about the resource leak warning when using Scanner.
I know I can close it, but the person in the video is not getting a warning even though he is using the exact same code, why is that?
Scanner input= new Scanner(System.in);
System.out.print("Enter a line of text: ");
String line = input.nextLine();
System.out.println("You entered: " + line);
//input.close();
The actual problem
It's.. complicated. The general rule is that whomever makes the resource must also safely close it, and because your code makes a Scanner, the IDE is telling you: Hey, you should close that.
The problem is, closing that scanner is wrong here: The scanner wraps around System.in, which is NOT a resource you made, but scanner.close() would close the underlying stream (System.in itself), and you don't want that: It's not your responsibility and in fact actively harms things; now you can never read from sysin again.
The problem is, the IDE can't really know this. The underlying problem is that System.in is extremely badly designed API in many many ways, but [A] it's 30 years old, back then it was a lot harder to know that; we know it now because of hindsight, and [B] oracle hasn't gotten around to making a second version of the sysin/out/err API yet, and it's not high on the agenda.
This leaves IDEs in trouble: It's relatively easy to set up some patterns and rules for using resources such that you never have any problems with this 'filters you created that wrap around resources you did not create', but you can't use them with sysin/err/out without writing a little framework, and that's a bit much to ask for newbies. It's also not a good idea presumably to tell those taking their first steps in java coding to first go download some third party library that cleans up sysin/out/err interaction a bit.
Thus, we're in limbo. IDEs should NOT warn about this, but it's hard for them to detect that this is an exotic sccenario where you have a resource you made that you nevertheless don't need to close, and in fact, should not close.
You can turn off the setting for 'unclosed resources', which no doubt the video tutorial did, but it is a useful warning. Just.. hampered by this silly old API that makes no sense anymore.
Some in-depth explanation
There are resources. These are things that implement AutoClosable, and there are very many. Let's focus on those that represent I/O things: The top level types in the hierarchy are Writer, Reader, InputStream, and OutputStream (let's call them all WRIOs). They're all AutoCloseable, and most IDEs (incorrectly?) all complain about unclosed resources for these. However, that's oversimplifying things.
You can split the world of all WRIOs into:
Actual resources (they directly represent an underlying OS-based concept that results to starvation of some resource, a.k.a. 'a leak', if you do not close them). new FileInputStream, socket.getInputStream - etc, these represent actual resources
Dummy resources - they act like a resource but don't actually represent a resource that you can starve out that isn't already fixed by the garbage collector. new ByteArrayInputStream, turning StringBuilders into Readers, etc.
filters - these wrap around a resource and modify it 'in transit'. Such filters do not themselves capture any starvable resource. If you close() them, they also invoke close on the thing they wrap. Scanner is a filter.
The rules on closing them boil down to:
Actual resources - must be closed safely by whomever made them. IDE warnings are warranted if you fail to do this. Note that you did not make System.in, so doesn't apply there.
Dummy resources - you can close them, but you don't have to. If the IDE warns on them, toss a try-with-resources around it, annoying but not too hard to work around.
Filters - tricky.
The problem with filters
If it's a filter provided to you with the intent that you close it:
BufferedReader br = Files.newBufferedReader(somePath);
then failure to close br is a resource leak; IDE warnings are warranted.
If it's a filter you made, wrapping around a WRIO you also made:
InputStream raw = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(raw, StandardCharsets.UTF_8));
(This is 1 real resource, wrapped by a filter WRIO (InputStreamReader), and then that filter wrapped by another filter WRIO): Then the resource leak is all about raw, and if you fail to safely close br, that's no resource leak. It might be a bug (if you close raw without closing/flushing br first, a bunch of bytes in the buffer won't have been written out), but not a resource leak. An IDE warning about failure to close br is wrong, but not too harmful, as you can just toss try-with-resources around it, and this in passing also guarantees that 'bug due to failure to flush out the buffering filter WRIO' cannot happen anymore.
Then, there is the problem case:
Making a filter WRIO that wraps around a resource you did not make and do not have the responsibility to close: You should actively NOT be closing these filter WRIOs, as that will end up closing the underlying resource and you did not want that.
Here an IDE warning is actively bad and annoying, but it is very hard for an IDE to realize this.
The design solution
Normally, you fix this by never getting in that scenario. For example, System.in should have better API; this API would look like:
try (Scanner s = System.newStandardIn()) {
// use scanner here
}
and have the property that closing s does not close System.in itself (it would do mostly nothing; set a boolean flag to throw exceptions if any further read calls are done, or possibly even do literally nothing). Now the IDE warning is at best overzealous, but heeding its advice and safely closing your scanner is now no longer actively introducing bugs in your code.
Unfortunately, that nice API doesn't exist (yet?). Thus we're stuck with this annoying scenario where a useful IDE warning system actively misleads you because of bad API design. If you really want to, you could write it:
public static Scanner newStandardIn() {
Scanner s = new Scanner(System.in) {
#Override public void close() {}
};
// hey, while we're here, lets fix
// another annoying wart!
s.useDelimiter("\r?\n");
return s;
}
Now you can heed those warnings by following its advice:
public static void main(String[] args) {
String name;
int age;
try (Scanner s = newStandardIn()) {
System.out.print("What is your name: ");
// use next() to read entire lines -
// that useDelimiter fix made this possible
name = s.next();
System.out.print("What is your age: ");
age = s.nextInt();
}
// use name and age here
}
no IDE warning, and no bugs.
I am creating an abstract binding class for a Reader and Writer where the user doesn't have to reference each one individually.
Example: I have a FileStream which inside of it houses both a FileReader and FileWriter.
The question I have refers to optimizing the class. I know I can't have two streams opened simultaneously due to concurrency, however I need to initialize them somewhere without having data leaks all over the place.
Are streams/readers/writers classified as being open, as soon as you initialize them, or are the 'pipes' only opened once the first read/write begins? I'm looking at the JavaDoc and don't see anything here about when the streams actually open up...
For those who do not understand what I am asking (ignoring try-catch blocks):
// does my reader become OPEN here?
BufferedReader br = new BufferedReader(new FileReader("foobar.txt"));
// or here, now that I have performed the first operation.
br.readLine();
They are open as soon as you construct them. There is no 'open' operation, so they are already open.
Discussion:
new FileInputStream(...) and new FileOutputStream(...) open the file, as they throw IOExceptions about it. Practically every other input or output stream extends FilterInput/OutputStream, with a FileInput/OutputStream as its delegate (including socket input/output streams as a matter of fact). The FileInput/OutputStream is created first in any such stack, ergo it is already open before the decorator streams, ergo they are already open too.
ByteArrayInput/OutputStreams and StringReader/Writer don't need opening at all.
Alternative solution: forget about re-inventing the wheel.
Java has a class that is specifically designed to allow for reading and writing to the same file: java.io.RandomAcessFile
So, if you have to wrap around... Use that class, instead of combining two other things that were never intended to be combined!
This is my understanding regarding reading a file using BufferedReader in java. Please correct me if I am wrong somewhere...
Recently I had a requirement where we are required to read a file multiple times.
The usual way which I use is setting a mark() and doing a reset. But the input parameters to
a mark is an integer and it cannot accept a long number. Is there a way in which we can read the file, a large number of times.
In c++ we can do a seekg on the fstream and read the contents once again irrespective of the number of times we want to do so. Is there anything in java which is of this nature.
Just close the file and read it again.
But review your requirement. Why can't you process it in one pass?
Not much of a good answer but if you want to do random reading and writing then you can use Channels in java.nio package.
BufferedReader is for reading a file when you logically see it as a series of records and records are generally accessed sequentially.
Channels allow you to view your file as a series of blocks. Blocks are meant to be read randomly. :)
Using subclass of channel, FileChannel, you can read what you want from wherever you want. You need to specify two things:
Where to read from.
How much to read.
It has a read(dst,pstn) where dst is a ByteBuffer and pstn is a long position.
Don't worry that it is abstract because you use it via Files.newByteChannel() which does all the voodoo needed to make it work :)
I want to intercept the standard output stream, then copy the content to another stream, but I also hope to keep the standard output stream like the original. Could I achieve that in Java?
You can use something like the example of TeeOutputStream explained here Writing Your Own Java I/O Stream Classes
Basically you create a TeeOutputStream, give it your stream and current System.out
then use System.setOut with the new stream.
Anything written to System.out will be written to the original System.out as well as your stream so you can do whatever you want with it
Edit:
Oracle took off this page, It is also possible to use TeeOutputStream from Apache Commons to do the same thing without adding any code.
Take a look at this package: org.apache.commons.io.output. I think that TeeOutputStream is what you're looking for.
I understand, how to convert AudioInputStream from one format to another. Now, when I have stream converted, how to write it to matching SourceDataLine I have?
Just loop over read() and write() methods? Or there are better premade methods?
Yes. Usually done in a while loop with a boolean to allow a means of stopping via an "external" thread.
There is a good example in the Java Tutorials, under the heading "Using a SourceDataLine".
http://docs.oracle.com/javase/tutorial/sound/playing.html
There are extra steps for opening and closing the lines, but the tutorial covers this as well.