This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I have a problem where by a section of my android app works fine on android version 4.1.2 but throws a NullPointerException when the same section is executed on android 4.4.3. My minimum sdk is set to 15 and target sdk is 21. Please find the code below:
try {
FileInputStream towe = new FileInputStream(path2);
re = new BufferedReader(new InputStreamReader(towe));
while ((res = re.readLine()) != null) {
result.append(res);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
re.close(); //ERROR IS GENERATED AT THIS LINE
} catch (IOException e) {
e.printStackTrace();
}
}
Morning guys, been away for a while. It turned out Exception was being thrown because of file path. I had hard-coded the path for android 4.1.2 but in 4.4.3 that path was different even though device was the same. I ended up using the
android.os.Environment.getExternalStorageDirectory();
method. Now working fine on both. Thanks for the suggestions
This is the correct way to write this, from a number of perspectives:
try (FileInputStream towe = new FileInputStream(path2);
Reader re = new BufferedReader(new InputStreamReader(towe))) {
while ((res = re.readLine()) != null) {
result.append(res);
}
}
Use try-with-resources. It is simpler, and more concise.
Don't catch an exception, and continue as if nothing happened. If you find yourself doing this, you are probably catching the exception in the wrong place.
Printing stacktraces in random places is a bad idea.
If you don't use try-with-resources then you need to test that re is non-null in the finally block to avoid the NPE. It would look like this with the erroneous stacktraces and exception squashing removed.
try {
FileInputStream towe = new FileInputStream(path2);
re = new BufferedReader(new InputStreamReader(towe));
while ((res = re.readLine()) != null) {
result.append(res);
}
} finally {
if (re != null) {
re.close();
}
}
And even then, there is a theoretical risk that towe won't be closed. (Hint: Error subclasses.)
NullPointerException on android 4.4.3 but not 4.1.2
What that most likely means is that new FileInputStream(path2); is throwing an exception (probably an IOException of some kind) on one platform and not the other. The clue is most likely in the I/O exception's message.
Related
I have recently scanned our code base with Fortify and I'm confused as to why it's flagging certain issues. One issue that I'm facing the issue is with releasing a resource.
Here is a snippet for context.
String someLocation = getPathToTheLocation(); //gives location
try (InputStream in = someLocation == null ? Thread.currentThread().getContextClassLoader()
.getResourceAsStream("someFile.xml") : new FileInputStream(new File(someLocation))) {
/// Do Something
}
Fortify complains that the method that has this try-with-resources block fails to release a system resource allocated by FileInputStream(). Doesn't the try-with-resources help me close the FileInputStream automatically?
Just assuming that Fortify doesn't recognize the try-with-resources paradigm, I refrained from using it and did it the regular way.
String someLocation = getPathToTheLocation(); //gives location
InputStream in = null;
try {
in = someLocation == null ? Thread.currentThread().getContextClassLoader().getResourceAsStream("someFile.xml")
: new FileInputStream(new File(someLocation));
//Do Something.
} finally {
assert in != null;
try {
in.close();
} catch (IOException ioe) {
throw new IllegalStateException("Could not close input stream.", ioe);
}
}
And yet it still complains about the resource being unreleased. What could be the actual issue here that I fail to recognize?
I think everything okay with the code, the problem in Fortify and maybe you should propose an Issue for it. There was quite the same issue with Idea - https://stackoverflow.com/a/34655863/5790043.
I have the following code which I am running through fortify. Why it gets marked for poor error handling, throw inside finally?
private String getResourceContent(String fileName) throws IOException {
try (InputStream resource = ErrorResource.classLoader.getResourceAsStream(fileName)) {
return new String(resource.readAllBytes(), StandardCharsets.UTF_8);
} catch (NullPointerException n) {
throw new ErrorDescriptorException(
String.format("Error loading Error description data from Resource file [%s].", fileName), n);
}
}
Explanation
This is explained very well in the official documentation (see Poor Error Handling: Throw Inside Finally). Let me quickly quote the important sections:
Using a throw statement inside a finally block breaks the logical progression through the try-catch-finally.
In Java, finally blocks are always executed after their corresponding try-catch blocks and are often used to free allocated resources, such as file handles or database cursors. Throwing an exception in a finally block can bypass critical cleanup code since normal program execution will be disrupted.
So you can easily bypass cleanup code by doing that, which leads to resource leaks.
Although not directly visible in your code, you actually have a hidden finally block since you are using try-with-resources which automatically closes the resource in a finally block.
Also see Throwing an exception inside finally where this was already discussed.
Example
Here is an example from the official documentation:
public void processTransaction(Connection conn) throws FileNotFoundException {
FileInputStream fis = null;
Statement stmt = null;
try {
stmt = conn.createStatement();
fis = new FileInputStream("badFile.txt");
...
} catch (FileNotFoundException fe) {
log("File not found.");
} catch (SQLException se) {
// handle error
} finally {
if (fis == null) {
// This bypasses cleanup code
throw new FileNotFoundException();
}
if (stmt != null) {
try {
// Not executed if the exception is thrown
stmt.close();
}
catch (SQLException e) {
log(e);
}
}
}
}
The call to stmt.close() is bypassed when the FileNotFoundException is thrown.
Note
Why are you checking for null using a NullPointerException instead of a basic if-else? There is rarely ever a valid reason to catch a NullPointerException. Just do:
try (InputStream resource = ErrorResource.classLoader.getResourceAsStream(fileName)) {
if (resource == null) {
// TODO Throw your exception here
}
return new String(resource.readAllBytes(), StandardCharsets.UTF_8);
}
It might also help to improve the error message by telling the exact reason that the resource could not be found.
Consider the following code, which is loosely based on yours:
String throwing(InputStream inputStream) throws IOException {
try (InputStream resource = inputStream) {
return "good";
} catch (NullPointerException n) {
return "bad";
}
}
You see, no exceptions thrown here. Still, you cannot remove the throws IOException bit – how’s that? Well, InputStream#close() can throw it, and it will be in the implicit finally block that the try-with-resources statement created. I guess there’s not much you can do about it, it looks like a Fortify false positive.
Beyond the misleading message from your tool, there is actually is poor error handling in your code, for multiple of reasons:
catching NPE is really bad practice. Either it is a bug (something that is null and shouldn't), or your code is missing a check if (whatever == null) and the corresponding code to deal with that expected situation
assuming that this NPE has exactly that meaning that you express in your new Exception is well, just guessing
In other words: without further information, it is not clear what exactly your tool complains about. But: one doesn't need a tool to understand: this is poor error handling.
Beyond that, such tools typically give some sort of information about their warnings. Meaning: there might be an "error id" coming with that warning, and you should be able to look up that "error id" in the documentation of your tool for further explanations.
new JarFile(path) can trow an I/O exception.
If that happens, and I catch the exception, should I close it? (I guess the real question is, is there anything to close?)
The other question is: if it works, should I clean up? I.e., do the general rules for dealing with streams apply?
Sorry if the question is a bit naff; I'm new to dealing with JarFile (and haven't really used streams in the past, either).
There is nothing to close if new JarFile(path) throws an IOException:
JarFile file = null;
try {
file = new JarFile("does/not/exist");
} catch (IOException e) {
System.out.println(file); //Prints out null
}
try {
file.close(); //Throws NullPointerException
} catch (IOException e) {
e.printStackTrace();
}
I'm reading a URL with the following code:
URL myURL = new URL("htpp://path_to_my_file");
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(myURL.openStream()));
while (reader.ready()) {
String line = reader.readLine();
...
}
} catch (IOException e) {
throw new RuntimeException("Parsing of file failed: " + myURL, e);
}
Could it happen, that the file is not read completely? (because of network problems or something else?). If yes, is there a way to test it or even to avoid?
The background: I'm working on an application (not written by me up to this point) and users report me that parts of files are missing sometimes. It happens sporadically so my only guess was that something sometimes fails when the file is read in but I have too few java-background to be sure...
Yes, you'll know it's happened when you get an IOException as per the Reader.readLine docs.
So you'll want to catch the Exception, something like this:
try {
while (reader.ready()) {
String line = reader.readLine();
}
}
catch(IOException e) {
// Bah! Humbug!
// Should really log this too. So if you're using Log4j:
log.error("Error reading from URL " + myURL.toString(), e);
} finally {
try { if (reader != null) reader.close(); }catch(Exception e){}
}
Somewhere here, I found the following comment:
ready() != has more
ready() does not indicate that there is more data to be read. It only shows if a read will could block the thread. It is likely that it will return false before you read all data.
To find out if there is no more data check if readLine() returns null
It sounds that the implementation with reader.ready() causes my problem. Am I wrong with this assumption?
Wrote up a basic file handler for a Java Homework assignment, and when I got the assignment back I had some notes about failing to catch a few instances:
Buffer from file could have been null.
File was not found
File stream wasn't closed
Here is the block of code that is used for opening a file:
/**
* Create a Filestream, Buffer, and a String to store the Buffer.
*/
FileInputStream fin = null;
BufferedReader buffRead = null;
String loadedString = null;
/** Try to open the file from user input */
try
{
fin = new FileInputStream(programPath + fileToParse);
buffRead = new BufferedReader(new InputStreamReader(fin));
loadedString = buffRead.readLine();
fin.close();
}
/** Catch the error if we can't open the file */
catch(IOException e)
{
System.err.println("CRITICAL: Unable to open text file!");
System.err.println("Exiting!");
System.exit(-1);
}
The one comment I had from him was that fin.close(); needed to be in a finally block, which I did not have at all. But I thought that the way I have created the try/catch it would have prevented an issue with the file not opening.
Let me be clear on a few things: This is not for a current assignment (not trying to get someone to do my own work), I have already created my project and have been graded on it. I did not fully understand my Professor's reasoning myself. Finally, I do not have a lot of Java experience, so I was a little confused why my catch wasn't good enough.
Buffer from file could have been null.
The file may be empty. That is, end-of-file is reach upon opening the file. loadedString = buffRead.readLine() would then have returned null.
Perhaps you should have fixed this by adding something like if (loadedString == null) loadedString = "";
File was not found
As explained in the documentation of the constructor of FileInputStream(String) it may throw a FileNotFoundException. You do catch this in your IOException clause (since FileNotFoundException is an IOException), so it's fine, but you could perhaps have done:
} catch (FileNotFoundException fnfe) {
System.err.println("File not fonud!");
} catch (IOException ioex {
System.err.println("Some other error");
}
File stream wasn't closed
You do call fin.close() which in normal circumstances closes the file stream. Perhaps he means that it's not always closed. The readLine could potentially throw an IOException in which case the close() is skipped. That's the reason for having it in a finally clause (which makes sure it gets called no matter what happens in the try-block. (*)
(*) As #mmyers correctly points out, putting the close() in a finally block will actually not be sufficient since you call System.exit(-1) in the catch-block. If that really is the desired behavior, you could set an error flag in the catch-clause, and exit after the finally-clause if this flag is set.
But what if your program threw an exception on the second or third line of your try block?
buffRead = new BufferedReader(new InputStreamReader(fin));
loadedString = buffRead.readLine();
By this point, a filehandle has been opened and assigned to fin. You could trap the exception but the filehandle would remain open.
You'll want to move the fin.close() statement to a finally block:
} finally {
try {
if (fin != null) {
fin.close();
}
} catch (IOException e2) {
}
}
Say buffRead.readLine() throws an exception, will your FileInputStream ever be closed, or will that line be skipped? The purpose of a finally block is that even in exceptional circumastances, the code in the finally block will execute.
There are a lot of other errors which may happen other than opening the file.
In the end you may end up with a fin which is defined or not which you have to protect against null pointer errors, and do not forget that closing the file can throw a new exception.
My advice is to capture this in a separate routine and let the IOExceptions fly out of it :
something like
private String readFile() throws IOException {
String s;
try {
fin = new FileInputStream(programPath + fileToParse);
buffRead = new BufferedReader(new InputStreamReader(fin));
s = buffRead.readLine();
fin.close();
} finally {
if (fin != null {
fin.close()
}
}
return s
}
and then where you need it :
try {
loadedString = readFile();
} catch (IOException e) {
// handle issue gracefully
}