I am working with Files in java and my IDE is VS-Code.The problem I am facing that it is showing the following as warnings alongwith a bunch of others-
Resource leak: 'sc' is never closed
Resource leak: 'scan' is never closed
where "sc" is defined as -
Scanner sc = new Scanner(System.in);
and "scan" as -
File fobj=new File("Marks.txt");
Scanner scan = new Scanner(fobj);
I am asking that Using #SuppressWarnings("resources") only blocks warning from Scanner object sc.Is there any way to block all of these open resources warnings which can be defined at the beginning of the Java file because I have to include #SuppressWarnings("resources") in every class I write.
You can add suppressions to the containing class:
#SuppressWarnings("resources")
class YourClass {
// ...
}
and this will suppress all resources warnings in the class.
This isn't such a great idea, though, because it will also suppress warnings about resources you do want to close, like scan.
I would say you've got a deeper problem if you're worried about adding suppressions in all the places where the warnings occur, because this implies you've got warnings in a lot of places.
In terms of suppressing the warning just on the Scanner sc = new Scanner(System.in);: you should only be creating a single scanner on a stream, and, as such, you should only need to add the suppression in one place.
If you're creating multiple scanners on System.in, you may get unexpected results from them, consider each scanner may consume part of the input stream. A better approach is to construct one scanner (on a given stream), and pass it around.
For Scanner scan, a better approach than suppressing the warning would be just to close the stream, so there is no warning to suppress. Try-with-resources guarantees this:
File fobj=new File("Marks.txt");
try (Scanner scan = new Scanner(fobj)) {
// ... Do stuff with scan.
}
// And now it's guaranteed to be closed.
Note that you can use try-with-resources around new Scanner(System.in), and it is guaranteed to be closed - but you shouldn't. Closing the Scanner closes the underlying stream - System.in.
You should only close streams that your code opened directly - your code didn't open System.in, the JVM did. System.in can't be reopened once closed, so you could accidentally break other parts of your code which assumed it would be open.
It's gross that you have to consider System.in and "other" streams separately - the "helpful" closing of child streams in Scanner (etc) is behavior that predates the try-with-resources syntax, so it's just something Java is stuck with.
Related
If I use FileSystems.getDefault().getPath() it holds resource at FileSystems.getDefault(). Few tools like sonar, coverity give high impact issues of resource leak for using this.
If I replace it with Paths.get() all the such tools quietly accept this and there is no error or warning of resource leak.
If we see the implementation of Paths.get(), it is literally doing FileSystems.getDefault().getPath()
My question here is, how does java handle resource leak for Paths.get() because the code is exactly same but we don't have reference to FileSystems.getDefault() to explicitly close it?
Your tools are reporting a false positive. That's because the declared type returned by FileSystems.getDefault(), FileSystem, implements Closeable. That means that ideally you should close it. However, the default file system is an exception (it even throws an UnsupportedOperationException). You're tools cannot make that distinction.
This happens more often than you'd think. Some examples I've seen too often:
The result of Objects.requireNonNull. The input is returned as-is, but if the input is AutoCloseable my IDE treats it as a new resource.
The input stream or reader from a servlet request, and the output stream or writer from a servet response.
There are some cases where tools and IDEs can be smart. For instance, if I declare a variable as ByteArrayInputStream, ByteArrayOutputStream, StringReader or StringWriter, then my IDE knows they don't need to be closed. However, when I return these from a method as InputStream, OutputStream, Reader or Writer respectively, my IDE starts complaining if I don't close them.
If you know that it is a false positive, you can use #SuppressWarnings("resource") to ignore warnings by some tools. That can often be applied to single variables:
#SuppressWarnings("resource") FileSystem defaultFS = FileSystems.getDefault();
Path path = defaultFS.getPath("foo");
However, even then sometimes your tools will complain, and you have to suppress the resource warnings for the entire method. If that's the case, try to keep your method (and therefore the scope of the warning suppression) as small as possible; split off code to a new method if needed.
Sonar complains that the Scanner should always be closed, is it right?
Scanner scanner = new Scanner("simple string")
This scanner is not scanning from file etc. Why should it be closed?
By calling new Scanner("string") it creates a StringReader which creates a character stream. So you have to close it.
See the OpenJDK source code
public Scanner(String source) {
this(new StringReader(source), WHITESPACE_PATTERN);
}
As specified in Sonar doc,
Connections, streams, files, and other classes that implement the
Closeable interface or its super-interface, AutoCloseable, needs to be
closed after use.
And Scanner does implement Closeable interface. Hence it should be closed.
Refer this link.
There is no need to close the Scanner, but it is better to do it in order to release the resources allocated for Scanner to optimize your code and make it faster and efficient.
The code below gives me a warning on Eclipse: "resource leak, input is never closed":
Code: 1
import java.util.Scanner;
public class Ex {
public void sum() {
Scanner input = new Scanner(System.in);
}
}
I found that declaring the input variable in the class level does the trick, the warning is gone.
But, is this the right way of fixing this issue? And what is the difference between the second code and the third code? Does code 3 means that I have abandoned the first object?
Code: 2
import java.util.Scanner;
public class Ex {
private Scanner input;
public void sum() {
input = new Scanner(System.in);
}
}
Code: 3
import java.util.Scanner;
public class Ex {
private Scanner input = new Scanner(System.in);
public void sum() {
input = new Scanner(System.in);
}
}
but , is this the right way of fixing this issue - No its not... The input is still not closed, only that Eclipse is not able to detect it anymore... The issue is still present...
That being said, it's not a good idea to close the Standard input System.in too (closing the Scanner object would close the underlying stream too as I understand)... Hence it would be better to leave it like that even though there is a warning...
Yes, since in code 3 you have reinitialized input, you have abandoned the first object.
The presence of a warning is almost always a sign of a problem. But the absence of a warning doesn't mean there is no problem.
The first snippet warns you that you're not closing the Scanner object when you're done with it. The proper fix would be to close it. Not to make your code worse by using a field instead of a local variable, and still not closing the scanner when you're done with it. That will make the warning disappear, but not the problem. Variables should always have the narrowest possible scope.
That said, A Scanner opened with System.in as argument, although it implements Closeable (that's why you have the warning), should in fact not be closed, because that would close the underlying stream: System.in. File or Socket streams must be closed, but System.in should generally not. If you close it, the user won't be able to enter anything anymore to your program.
You are getting the warning because the scanner instance is never closed. Modify the code: 1 as below to eliminate the warning,
public void sum() {
Scanner input = null;
try {
input = new Scanner(System.in);
// do operation
} finally {
input.close();
}
}
Regarding code:2, declare any variable at Object level only when its required. i.e if it needs to be accessed by multiple member functions defined in the class.
To answer your question is this the right way of fixing this issue , and what is the difference between the second code and the third code ? Does code : 3 means that i have abandoned the first object ?
No, Code: 3 is not the right way way to fix the issue. And yes, code:3 creates a new instance of scanner inside the member function "sum" and the reference of the member variable input will point to the newly created scanner instance.
In summary, create a member variable (object level) only when its absolutely required, otherwise create a local variable - this will ensure that the objects get collected much earlier. (i.e. these objects will become eligible for GC when the method execution completes). Also, make sure that, call close() on almost all of the IO classes (stream classes) that we operate on.
Also, Note that if you close System.in, you won't be able to read from it again
I have a program in java, in which I have to get user input, however, I only need to get the user input once, after that, I do not need a scanner anymore. Doing the following:
int userInput = new Scanner(System.in).nextInt();
Gives me a Resource Leak warning, saying that <unassigned closeable value> is never closed.
Is there another way I can use a Scanner only once, and get rid of it afterwards so there's no Resource Leak? Maybe something similar to C#'s using statement.
The equivalent to C#'s using is a try-with-resources. Don't use that, it will close the System.in and you don't want that. Ignore the warning for this particular case. Let the garbage collector claim the Scanner and leave the standard input as is.
I can see the following two options...
Option #1 : Explicitly close the scanner as soon as you read the input once.
Scanner sc = new Scanner(System.in);
int userInput = sc.nextInt();
sc.close();
Option #2 : Use the try-with-resource statement
try(Scanner sc1 = new Scanner(System.in)) {
int userInput1 = sc1.nextInt();
}
The downside of option #2 is that it will close all the resources that exist in try-with-resource statement, which included System.in.
Java has Automatic garbage collection. Automatic garbage collection is the process of looking at heap memory, identifying which objects are in use and which are not, and deleting the unused objects. An in use object, or a referenced object, means that some part of your program still maintains a pointer to that object. An unused object, or unreferenced object, is no longer referenced by any part of your program. So the memory used by an unreferenced object can be reclaimed.
This means you shall not to worry about this type of warnings. Additionally in Eclipse you can use#SuppressWarning to get rid of annoying warnings.
I have a Scanner linked to System.in. Now, after using the Scanner, I should close it, as it is bad coding practice to leave it open. But, if I close the Scanner, I will also be closing System.in! Can anyone tell me how I can close the Scanner without closing System.in (if there is any way).
The simplest thing is to not close Scanner if you don't want to close the underlying stream.
Ideally you should create just one Scanner which you use for the life of the program. In any case, it appears you don't have a good reason to close it.
One option is to wrap your System.in stream in a CloseShieldInputStream that prevents it from being closed. Your reader would then use the CloseShieldInputStream rather than the raw System.in stream.
Here is the API for the class:
http://commons.apache.org/io/apidocs/org/apache/commons/io/input/CloseShieldInputStream.html
Instead of adding shield classes and stuff like that, just put a nice comment and a
#SuppressWarnings("resource")
That's good enough. And I don't seem to see a lot of drawbacks to this approach. Don't forget the comment.
I have vague memories of strange, undiagnosable problems long ago with using the same Scanner of System.in twice, so this is what I use (even though you should probably just use one scanner for the duration of the program):
static String input() {
try {
return new Scanner(System.in).nextLine();
} catch (NoSuchElementException e) {
throw e;
}
}
For some reason this works without warnings, whereas if I don't do the catch-throw, Eclipse will complain Resource leak: '<unassigned Closeable value>' is never closed.
According to the API for InputSteam "The close method of InputStream does nothing.", so since System.in is an instance of InputStream, you don't need to worry about close() being called on it.