In what situations should one catch java.lang.Error on an application?
Generally, never.
However, sometimes you need to catch specific errors.
If you're writing framework-ish code (loading 3rd party classes), it might be wise to catch LinkageError (no class def found, unsatisfied link, incompatible class change).
I've also seen some stupid 3rd-party code throwing subclasses of Error, so you'll have to handle those as well.
By the way, I'm not sure it isn't possible to recover from OutOfMemoryError.
Never. You can never be sure that the application is able to execute the next line of code. If you get an OutOfMemoryError, you have no guarantee that you will be able to do anything reliably. Catch RuntimeException and checked Exceptions, but never Errors.
http://pmd.sourceforge.net/rules/strictexception.html
In multithreaded environment, you most often want to catch it! When you catch it, log it, and terminate whole application! If you don't do that, some thread that might be doing some crucial part would be dead, and rest of the application will think that everything is normal. Out of that, many unwanted situations can happen.
One smallest problem is that you wouldn't be able to easily find root of the problem, if other threads start throwing some exceptions because of one thread not working.
For example, usually loop should be:
try {
while (shouldRun()) {
doSomething();
}
}
catch (Throwable t) {
log(t);
stop();
System.exit(1);
}
Even in some cases, you would want to handle different Errors differently, for example, on OutOfMemoryError you would be able to close application regularly (even maybe free some memory, and continue), on some others, there is not much you can do.
Generally you should always catch java.lang.Error and write it to a log or display it to the user. I work in support and see daily that programmers cannot tell what has happened in a program.
If you have a daemon thread then you must prevent it being terminated. In other cases your application will work correctly.
You should only catch java.lang.Error at the highest level.
If you look at the list of errors you will see that most can be handled. For example a ZipError occurs on reading corrupt zip files.
The most common errors are OutOfMemoryError and NoClassDefFoundError, which are both in most cases runtime problems.
For example:
int length = Integer.parseInt(xyz);
byte[] buffer = new byte[length];
can produce an OutOfMemoryError but it is a runtime problem and no reason to terminate your program.
NoClassDefFoundError occur mostly if a library is not present or if you work with another Java version. If it is an optional part of your program then you should not terminate your program.
I can give many more examples of why it is a good idea to catch Throwable at the top level and produce a helpful error message.
Very rarely.
I'd say only at the top level of a thread in order to ATTEMPT to issue a message with the reason for a thread dying.
If you are in a framework that does this sort of thing for you, leave it to the framework.
Almost never. Errors are designed to be issues that applications generally can't do anything about. The only exception might be to handle the presentation of the error but even that might not go as planned depending on the error.
An Error usually shouldn't be caught, as it indicates an abnormal condition that should never occur.
From the Java API Specification for the Error class:
An Error is a subclass of Throwable
that indicates serious problems that a
reasonable application should not try
to catch. Most such errors are
abnormal conditions. [...]
A method is not required to declare in
its throws clause any subclasses of
Error that might be thrown during the
execution of the method but not
caught, since these errors are
abnormal conditions that should never
occur.
As the specification mentions, an Error is only thrown in circumstances that are
Chances are, when an Error occurs, there is very little the application can do, and in some circumstances, the Java Virtual Machine itself may be in an unstable state (such as VirtualMachineError)
Although an Error is a subclass of Throwable which means that it can be caught by a try-catch clause, but it probably isn't really needed, as the application will be in an abnormal state when an Error is thrown by the JVM.
There's also a short section on this topic in Section 11.5 The Exception Hierarchy of the Java Language Specification, 2nd Edition.
If you are crazy enough to be creating a new unit test framework, your test runner will probably need to catch java.lang.AssertionError thrown by any test cases.
Otherwise, see other answers.
And there are a couple of other cases where if you catch an Error, you have to rethrow it. For example ThreadDeath should never be caught, it can cause big problem is you catch it in a contained environment (eg. an application server) :
An application should catch instances of this class only if it must clean up
after being terminated asynchronously. If ThreadDeath is caught by a method,
it is important that it be rethrown so that the thread actually dies.
Very, very rarely.
I did it only for one very very specific known cases.
For example, java.lang.UnsatisfiedLinkError could be throw if two independence ClassLoader load same DLL. (I agree that I should move the JAR to a shared classloader)
But most common case is that you needed logging in order to know what happened when user come to complain. You want a message or a popup to user, rather then silently dead.
Even programmer in C/C++, they pop an error and tell something people don't understand before it exit (e.g. memory failure).
In an Android application I am catching a java.lang.VerifyError. A library that I am using won't work in devices with an old version of the OS and the library code will throw such an error. I could of course avoid the error by checking the version of OS at runtime, but:
The oldest supported SDK may change in future for the specific library
The try-catch error block is part of a bigger falling back mechanism. Some specific devices, although they are supposed to support the library, throw exceptions. I catch VerifyError and all Exceptions to use a fall back solution.
it's quite handy to catch java.lang.AssertionError in a test environment...
Ideally we should not handle/catch errors. But there may be cases where we need to do, based on requirement of framework or application. Say i have a XML Parser daemon which implements DOM Parser which consumes more Memory. If there is a requirement like Parser thread should not be died when it gets OutOfMemoryError, instead it should handle it and send a message/mail to administrator of application/framework.
ideally we should never catch Error in our Java application as it is an abnormal condition. The application would be in abnormal state and could result in carshing or giving some seriously wrong result.
It might be appropriate to catch error within unit tests that check an assertion is made. If someone disables assertions or otherwise deletes the assertion you would want to know
There is an Error when the JVM is no more working as expected, or is on the verge to. If you catch an error, there is no guarantee that the catch block will run, and even less that it will run till the end.
It will also depend on the running computer, the current memory state, so there is no way to test, try and do your best. You will only have an hasardous result.
You will also downgrade the readability of your code.
Related
I have been working on an Android app which uses try/catch frequently to prevent it from crashing even on places where there is no need. For example,
A view in xml layout with id = toolbar is referenced like:
// see new example below, this one is just confusing
// it seems like I am asking about empty try/catch
try {
View view = findViewById(R.id.toolbar);
}
catch(Exception e) {
}
This approach is used throughout the app. The stack trace is not printed and it's really hard to find what went wrong. The app closes suddenly without printing any stack trace.
I asked my senior to explain it to me and he said,
This is for preventing crashing in production.
I totally disagree with it. To me this is not the way to prevent apps from crashes. It shows that developer doesn't know what he/she is doing and is in doubt.
Is this the approach being used in industry to prevent enterprise apps from crashes?
If try/catch is really, really our need then is it possible to attach an exception handler with UI thread or other threads and catch everything there? That will be a better approach if possible.
Yes, empty try/catch is bad and even if we print stack trace or log exception to server, wrapping blocks of code in try/catch randomly across all the app doesn't make sense to me e.g. when every function is enclosed in a try/catch.
UPDATE
As this question has got a lot of attention and some people have misinterpreted the question (perhaps because I haven't phrased it clearly) I am going to rephrase it.
Here is what developers are doing here
A function is written and tested, it can be a small function which just initializes views or a complex one, after testing it is wrapped around try/catch block. Even for function which will never throw any exception.
This practice is used throughout the application. Sometime stack trace is printed and sometime just a debug log with some random error message. This error message differ from developer to developer.
With this approach, app does not crash but behavior of the app becomes undetermined. Even sometime it is hard to follow what went wrong.
The real question I have been asking was; Is it the practice being following in the industry for preventing the enterprise applications from crashes? and I am not asking about empty try/catch. Is it like, users love application which do not crash than applications which behave unexpectedly? Because it really boils down to either crash it or present the user with a blank screen or the behaviour user is unaware of.
I am posting a few snippets from the real code here
private void makeRequestForForgetPassword() {
try {
HashMap<String, Object> params = new HashMap<>();
String email= CurrentUserData.msisdn;
params.put("email", "blabla");
params.put("new_password", password);
NetworkProcess networkProcessForgetStep = new NetworkProcess(
serviceCallListenerForgotPasswordStep, ForgotPassword.this);
networkProcessForgetStep.serviceProcessing(params,
Constants.API_FORGOT_PASSWORD);
} catch (Exception e) {
e.printStackTrace();
}
}
private void languagePopUpDialog(View view) {
try {
PopupWindow popupwindow_obj = popupDisplay();
popupwindow_obj.showAsDropDown(view, -50, 0);
} catch (Exception e) {
e.printStackTrace();
}
}
void reloadActivity() {
try {
onCreateProcess();
} catch (Exception e) {
}
}
It is not duplicate of Android exception handling best
practices, there OP is trying to catch exception for a different
purpose than this question.
Of course, there are always exceptions to rules, but if you need a rule of thumb - then you are correct; empty catch blocks are "absolutely" bad practice.
Let's have a closer look, first starting with your specific example:
try {
View view = findViewById(R.id.toolbar);
}
catch(Exception e) { }
So, a reference to something is created; and when that fails ... it doesn't matter; because that reference isn't used in the first place! The above code is absolutely useless line noise. Or does the person who wrote that code initially assume that a second, similar call would magically no longer throw an exception?!
Maybe this was meant to look like:
try {
View view = findViewById(R.id.toolbar);
... and now do something with that view variable ...
}
catch(Exception e) { }
But again, what does this help?! Exceptions exist to communicate respectively propagate error situations within your code. Ignoring errors is rarely a good idea. Actually, an exception can be treated in ways like:
You give feedback to the user; (like: "the value you entered is not a string, try again"); or to engage in more complex error handling
Maybe the problem is somehow expected and can be mitigated (for example by giving a "default" answer when some "remote search" failed)
...
Long story short: the minimum thing that you do with an exception is to log/trace it; so that when you come in later debugging some problem you understand "OK, at this point in time that exception happened".
And as others have pointed out: you also avoid catching for Exception in general (well, depending on the layer: there might be good reasons to have some catch for Exception, and even some kinds of Errors at the highest level, to make sure that nothing gets lost; ever).
Finally, let's quote Ward Cunningham:
You know you are working with clean code when each routine you read turns out to be pretty much what you expected. You can call it beautiful code when the code also makes it look like the language was made for the problem.
Let that sink in and meditate about it. Clean code does not surprise you. The example you are showing to us surprises everybody looking at.
Update, regarding the update that the OP asks about
try {
do something
}
catch(Exception e) {
print stacktrace
}
Same answer: doing that "all over the place" is also bad practice. Because this code is also surprising the reader.
The above:
Prints error information somewhere. It is not at all guaranteed that this "somewhere" resembles a reasonable destination. To the contrary. Example: within the application I am working with, such calls would magically appear in our trace buffers. Depending on context, our application might pump tons and tons of data into those buffers sometimes; making those buffer prune every few seconds. So "just printing errors" often translates to: "simply loosing all such error information".
Then: you don't do try/catch because you can. You do it because you understand what your code is doing; and you know: I better have a try/catch here to do the right thing (see the first parts of my answer again).
So, using try/catch as "pattern" like you are showing; is as said: still not a good idea. And yes, it prevents crashes; but leads to all kind of "undefined" behavior. You know, when you just catch an exception instead of properly dealing with it; you open a can of worms; because you might run into myriads of follow-on errors that you later don't understand. Because you consumed the "root cause" event earlier on; printed it somewhere; and that somewhere is now gone.
From the Android documentation:
Let's entitle it as -
Don't Catch Generic Exception
It can also be tempting to be lazy when catching exceptions and do something like this:
try {
someComplicatedIOFunction(); // may throw IOException
someComplicatedParsingFunction(); // may throw ParsingException
someComplicatedSecurityFunction(); // may throw SecurityException
// phew, made it all the way
} catch (Exception e) { // I'll just catch all exceptions
handleError(); // with one generic handler!
}
In almost all cases it is inappropriate to catch generic Exception or Throwable (preferably not Throwable because it includes Error exceptions). It is very dangerous because it means that Exceptions you never expected (including RuntimeExceptions like ClassCastException) get caught in application-level error handling.
It obscures the failure handling properties of your code, meaning if someone adds a new type of Exception in the code you're calling, the compiler won't help you realize you need to handle the error differently.
Alternatives to catching generic Exception:
Catch each exception separately as separate catch blocks after a single try. This can be awkward but is still preferable to catching all Exceptions.
Edit by author: This one is my choice. Beware repeating too much code in the catch blocks. If you are using Java 7 or above, use multi-catch to avoid repeating the same catch block.
Refactor your code to have more fine-grained error handling, with multiple try blocks. Split up the IO from the parsing, handle errors separately in each case.
Re-throw the exception. Many times you don't need to catch the exception at this level anyway, just let the method throw it.
In most cases you shouldn't be handling different types of exception the same way.
Formatting / paragraphing slightly modified from the source for this answer.
P.S. Don't be afraid of Exceptions!! They are friends!!!
I would put this as a comment to some other answer, but I don't have the reputation for that yet.
You are correct in saying that it's bad practice, in fact what you posted shows different types of bad practice in regards to exceptions.
Lack of error handling
Generic Catch
No intentional exceptions
Blanket Try/catch
I'll try to explain all of those via this example.
try {
User user = loadUserFromWeb();
if(user.getCountry().equals("us")) {
enableExtraFields();
}
fillFields(user);
} catch (Exception e) {
}
This can fail in several ways that should be handled differently.
The fields will not be filled, so the user is presented with an empty screen and then... what? Nothing - lack of error handling.
There's no distinction between different types of errors, e.g. Internet problems or problems with the server itself (outage, broken request, corrupted transmission, ...) - Generic catch.
You can not use exceptions for your own purposes because the current system interferes with that. - No intentional exceptions
Unessential and unexpected errors (e.g. null.equals(...)) can cause essential code not to execute. - Blanket try/catch
Solutions
(1) First of all, failing silently is not a good thing. If there's a failure, the app won't work. Instead there should be an attempt to resolve the problem or a display a warning, for example "Could not load user data, maybe you're not connected to the Internet?". If the app is not doing what it's supposed to, that's way more frustrating for a user than if it just closes itself.
(4) If the User is incomplete, e.g. the country is not known and returns null. The equals method will create a NullPointerException. If that NPE is just thrown and caught like above, the fillFields(user) method will not be called, even though it could still be executed without problems. You could prevent this by including null checks, changing execution order, or adjusting the try/catch scope. (Or you could do save coding like this: "us".equals(user.getCountry()), but I had to provide an example). Of course any other exception will also prevent fillFields() from being executed, but if there's no user, you probably don't want it executed anyway.
(1, 2, 3)Loading from web often throws a variety of exceptions, from IOException to HttpMessageNotReadable exception to even just returning. Could be that the user isn't connected to the internet, could be that there was a change to a backend server or it is down, but you don't know because you do catch(Exception) - instead you should catch specific exceptions. You can even catch several of them like this
try{
User user = loadUserFromWeb(); //throws NoInternetException, ServerNotAvailableException or returns null if user does not exist
if(user == null) {
throw new UserDoesNotExistException(); //there might be better options to solve this, but it highlights how exceptions can be used.
}
fillFields(user);
if("us".equals(user.getCountry()) {
enableExtraFields();
}
} catch(NoInternetException e){
displayWarning("Your internet conneciton is down :(");
} catch(ServerNotAvailableException e){
displayWarning("Seems like our server is having trouble, try again later.");
} catch(UserDoesNotExistException e){
startCreateUserActivity();
}
I hope that explains it.
At the very least as a quick fix, what you could do is send an event to your backend with the exception. For example through firebase or crashlytics. That way you can at least see stuff like (hey, the main activity does not load for 80% of our users due to a problem like (4).
It's definitely a bad programming practice.
From the current scenario, if there are hundreds of try catch like this, then you won't even know where the exception occurs without debugging the application, which is a nightmare if your application is in production environment.
But you can include a logger so that you get to know when an exception is throws (and why). It won't change your normal workflow.
...
try {
View view = findViewById(R.id.toolbar);
}catch(Exception e){
logger.log(Level.SEVERE, "an exception was thrown", e);
}
...
This is bad practice. Other answers have said that but I'd think it's important to step back and understand why we have exceptions in the first place.
Every function has a post-condition – a set of things that must all be true after that function executes. For example, a function that reads from a file has the post condition that the data in the file will be read from disk and returned. An exception, then, is thrown when a function has not been able to satisfy one of its post-conditions.
By ignoring an exception from a function (or even effectively ignoring it by simply logging the exception), you're saying that you're ok with that function not actually doing all the work it agreed to do. This seems unlikely – if a function does not run correctly, there is no guarantee that what follows will run at all. And if the rest of your code runs fine whether or not a particular function runs to completion, then one wonders why you have that function in the first place.
[Now there are certain cases where empty catches are ok. For example, logging is something that you might justify wrapping in an empty catch. Your application will probably run fine even if some of the logging can't be written. But those are special cases that you have to work really hard to find in a normal app.]
So the point is, this is bad practice because it doesn't actually keep your app running (the supposed justification for this style). Maybe technically the OS hasn't killed it. But it's unlikely that the app is still running properly after simply ignoring an exception. And in the worst case, it could actually be doing harm (e.g. corrupting user files, etc.).
This is bad for multiple reasons:
What are you doing that findViewById throws an Exception? Fix that (and tell me, because I've never seen this) instead of catching.
Don't catch Exception when you could catch a specific type of exception.
There is this belief that good apps don't crash. That's not true. A good app crashes if it must.
If an app goes into a bad state, it is much better for it to crash than for it to chug along in its unusable state. When one sees an NPE, one shouldn't just stick in a null check and walk away. The better approach is to find out why something is null and either stop it from being null, or (if null ends up being a valid and expected state) check for null. But you have to understand why the issue occurs in the first place.
I have been developing android apps for the past 4-5 years and never used a try catch for view initialisation.
If its a toolbar do like this
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
eg:- To get a TextView from a view(fragment/dialog/any custom view)
TextView textview = (TextView) view.findViewById(R.id.viewId);
TextView textview = (TextView) view.findViewById(R.id.viewId);
instead of this
View view = findViewById(R.id.toolbar);
A view object has minimum reach compared to its real view type.
Note:- May be it crashed because the view was loaded. But adding try catch is a bad practice.
Yes, try/catch is used to prevent app from crashing but You certainly don't need try/catch for fetching a view from XML as depicted in your question.
try/catch is generally used while making any http request, while parsing any String to URL, creating URL connections, etc. and also make sure to print stack trace. Not printing it doesn't make much sense in surrounding it with try/catch.
As said before, general exceptions shouldn't be catched, or at least only in a few central places (usually located in framework/infrastructure code, not application code). If catching general exceptions and logging it, the application should be shut down afterwards, or at the very least user should be informed that application is potentially in a unstable state and data corruption could occur (if user chooses to continue execution). Because this is what might happen if you catch all sort of exceptions (out of memory to name one) and leaving the app in an undefined state.
IMHO it is worse to swallow exceptions and risk data integrity, data loss, or simply leaving the app in an undefined state than letting the app crash and the user knows that something went wrong and can try again. This will also lead to better issues reported (more at the root of the problem), probably fewer different symptoms than if your users start to report all kind of troubles originating from undefined application state.
After a central exception handling/logging/reporting and controlled shutdown is in place, start rewriting exception handling to catch local exceptions as specific as possible. Try to make the try{} block as short as possible.
Let me add my point of view, as a guy working in the corporate mobile development industry for more than a decade. First, some general tips on exceptions, most of them included in answers above:
Exceptions should be used for exceptional, unexpected or uncontrolled situations, not on a regular basis throughout the code.
A programmer must know the portions of code susceptible to throw exceptions and try-catch them, leaving the rest of the code as clean as possible.
Exceptions should not be left silent, as a general rule.
Now, when you are not developing an app for yourself, but for a company or a corporation, it is common to face additional requirements on this topic:
"App crashes show a poor image of the company, so they are not acceptable". Then, careful development should be performed, and catching even improbable exceptions may be an option. If so, this must be done selectively and kept in reasonable limits. And notice that development is not all about lines of code, for instance, an intensive testing process is critical in these cases. However, unexpected behaviour in a corporate app is worse than crashing. So, whenever you catch an exception in your app, you must know what to do, what to show and how the app will behave next. If you cannot control that, better let the app crash.
"Logs and stack traces may dump sensitive information to the console. That might be used for an attacker, so for security reasons they cannot be used in a production environment". This requirement conflicts with the general rule for a developer not to write silent exceptions, so you have to find a way for it. For instance, your app could control the environment, so it uses logs and stack traces in non-production environments, while using cloud-based tools like bugsense, crashlitics or similar for production environments.
So, the short answer is that the code you found it is not a good practice example, since it is hard and costly to maintain without improving the quality of the app.
Another perspective, as someone who writes enterprise software on a daily basis, if an app has an unrecoverable error, I want it to crash. Crashing is desirable. If it crashes, it gets logged. If it crashes more than a few times in a short period of time, I get an e-mail saying that the app is crashing and I can verify that our app and all the web services we consume are still working.
So the question:
Is
try{
someMethod();
}catch(Exception e){}
good practice? No! Here are a few points:
The MOST important thing: This is a bad customer experience. How am I supposed to know when something bad is happening? My customers are trying to use my app and nothing works. They can't check their bank account, pay their bills, whatever my app does. My app is completely useless, but hey, at least it didn't crash! (Part of me believes this "Senior" dev gets brownie points for low crash numbers, so they're gaming the system.)
When I'm doing development and I write bad code, if I'm just catching and swallowing all exceptions at the top layer I have no logging. I have nothing in my console, and my app fails silently. From what I can tell, everything appears to work okay. So I commit the code... Turns out my DAO object was null the whole time, and the customer's payments were never actually updating in the DB. Whoops! But my app didn't crash, so that's a plus.
Playing devil's advocate, let's say I was okay with catching and swallowing every exception. It's extremely easy to write a custom exception handler in Android. If you really just have to catch every exception, you can do it in one place and not pepper try/catch all over your codebase.
Some of the developers I've worked with in the past have thought crashing was bad.
I have to assure them we want our app to crash. No, an unstable app is not okay, but a crash means we did something wrong and we need to fix it. The faster it crashes, the earlier we find it, the easier it is to fix. The only other option I can think of is allowing the user to continue in a broken session, which I equate with pissing off my userbase.
It's bad practice to use catch(Exception e){} because you're essentially ignoring the error. What you probably want to do is something more like:
try {
//run code that could crash here
} catch (Exception e) {
System.out.println(e.getMessage());
}
We pretty use much your same logic. Use try-catch to prevent production apps from crashing.
Exceptions should be NEVER ignored. It is a bad coding practice. The guys maintaining the code will have a really hard time localizing the part of code that raised the exception if they are not logged.
We use Crashlytics to log the exceptions. The code will not crash (but some functionality will be disrupted). But you get the exception log in the dashboard of Fabric/Crashlytics. You can look at these logs and fix the exceptions.
try {
codeThatCouldRaiseError();
} catch (Exception e) {
e.printStackTrace();
Crashlytics.logException(e);
}
While I agree with the other responses, there is one circumstance I have repeatedly encountered where this motif is marginally tolerable. Suppose someone wrote a bit of code for a class as follows:
private int foo=0;
. . .
public int getFoo() throws SomeException { return foo; }
In this circumstance, the 'getFoo()' method cannot fail - there will always be a legitimate value of the private field 'foo' to be returned. Yet someone - probably for pedantic reasons - decided that this method should be declared as potentially throwing an Exception. If you then try to call this method in a context - e.g an event handler - which does not allow an exception to be thrown, you are basically forced to use this construct (even then, I agree that one should at least log the exception just in case). Whenever I have to do this, I always at least add a big fat comment 'THIS CANNOT OCCUR' next to the 'catch' clause.
I have been reading the JLS and I encountered the section 11.1.3. Asynchronous Exceptions from which I quote:
Most exceptions occur synchronously as a result of an action by the
thread in which they occur, and at a point in the program that is
specified to possibly result in such an exception. An asynchronous
exception is, by contrast, an exception that can potentially occur at
any point in the execution of a program.
And
Asynchronous exceptions occur only as a result of:
[...]
An internal error or resource limitation in the Java virtual machine that prevents it from implementing the semantics of the
Java programming language. In this case, the asynchronous exception
that is thrown is an instance of a subclass of VirtualMachineError.
Is it possible to catch such exceptions for logging purposes or notification (because I believe such thing is unrecoverable)? How can I achieve such thing?
You can catch such exceptions just like any other exception. The only problem is that they may occur at any place in your program, so catching them reliably is hard. You would basically have to wrap the run method of all threads and the main method in a try..catch block, but you can't do that for threads you don't control (like the Swing EDT, or threads for timers etc.).
Also catching any subclass of Error is usually not recommended, because the JVM may be in an unstable state, which might lead to a further failure (for example in the case of OutOfMemoryError, you might not even have enough memory to to the exception handling). However, logging would be a valid reason for catching Errors in my eyes.
My suggested solution would be to use an uncaught exception handler for this by setting it as the default exception handler. In this handler you will get all exceptions and errors, if they are not caught anywhere in the code, and you can try to log them.
There is no point of catching these exceptions (Subclasses of VirtualMachineError) as you have no indecattion in which state the pogram is at the point, the Doc saies about Virtual Machine Errors:
A Java virtual machine implementation throws an object that is an
instance of a subclass of the class VirtualMethodError when an
internal error or resource limitation prevents it from implementing
the semantics described in this chapter. This specification cannot
predict where internal errors or resource limitations may be
encountered and does not mandate precisely when they can be reported.
so assuming you get in an OutOfMemoryError or an UnknownError there isnt much you can do about it, and once your vritualmashine doesnt work properly you cant provide the user anyhelp as your program isnt working properly as well, besides you have no idea at what time, point, and reason it happends since its not a code error that was caused from your program.
I have tried looking for an answer to this on other threads, but so far I have only seen threads that state that catching Throwable is bad. My question is, is there ever a reason why you would WANT to do this and then do nothing in the catch block except print out the stack trace?
I was recently brought onto a project and given the task of cleaning up the error handling of an existing set of classes for a RESTful service. Several of the helper service classes have try/catch blocks that only catch Throwable and print out the stack trace, as shown below:
class MainService {
SubService1 s1;
SubService2 s2;
public doMainService() {
}
}
class SubService1 {
public int findSomething() {
try {
// Do Something
} catch (Throwable t) {
t.printStackTrace();
}
}
}
class SubService2 {
public int findSomethingElse() {
try {
// Do Something
} catch (Throwable t) {
t.printStackTrace();
}
}
}
Is there a case that this is acceptable? Would it be better for the methods to throw Exception and not have the try/catch blocks?
This is almost never a good practice for a variety of well known reasons.
In particular, it doesn't distinguish between checked and unchecked exceptions and errors. More importantly, one of the effects of this code is allowing the application to execute beyond the exception handler which may result in all kinds of strange behavior due to violated invariants. In other words, since the exception caught may be really anything including violated assertions, programming errors, thread interruptions, missing classes, I/O errors, OOM conditions and even library and VM bugs, the program state is practically unpredictable beyond the exception handler.
In some rare situations broad exception handling may make sense. Imagine a server handling multiple independent requests. You may not want to crash due to a problem encountered while serving one of the requests. Since you do not rely on the state left after the exception handler, you can simply print the stack trace and let someone investigate while the server continues serving other requests.
Even in these situations one should carefully consider whether errors, e.g. VirtualMachineError should really be caught.
One reason that I think people do this is just because Java forces you to either surround calls that throw with a try/catch block, or add throws to the method declaration.
If you "know" that you're not going to have an exception occur, then it's kind of a way to prevent it from going up the chain (cause if you do throws, who ever calls your code needs to surround with a try/catch and so on), but if something does occur it'll dump it without crashing.
You might do that if you don't know any other way to get the stack trace and you want to know how you got to your current location. Not a very good reason, but a possible one. This doesn't seem to fit what you're looking at though; you seem to have been given code which doesn't crash but also doesn't do a good job with error handling.
I use it to see exactly where my program is crashing. So basically just for debugging. Also just to see if it's flowing in the way expected.
It is possible that they wanted to see the stack trace without crashing the program.
For example it can be appropriate for code executed by a thread to log exceptions but otherwise do nothing when it is unacceptable for the thread to crash since the next iteration (say where threads are taking items from a queue) may work as expected. This depends on the use case, but for a server you generally want the threads to be bullet proof and log any errors, instead of halting any further processing (but use cases may vary).
Most simplest example we come across in your problem is when it comes to close an input stream.Follwoing is the method declaration in InputStream class.
public void close() throws IOException
Althoug there is a possiblity to throw an exception when we call this method it would be no harm for the program execution.(Since we will not use that InputStream further) In that case we should only log the error and continue the program. But if you find out an exception which change the states of an object and then you must think about recovery code or halt execution.
Never do this (e.printStackTrace()). many IDE's default to it, but its horrible (many apps run with stderr redirected in ways that are not accessible, and thus, never seen). rules of thumb:
if you truly don't care about the exception (never, ever, ever, ever will care), catch it and do nothing with a big comment which says "we really, really don't ever care if this exception gets thrown"
if you never expect an exception to actually be thrown (the interface defines a checked exception, but you know the impl doesn't actually throw it), rethrow the exception as something like new UnsupportedOperationException("this should never happen", t) (that way if/when the underlying impl gets changed you find out about it sooner rather than later)
if you expect that the exception is unlikely, and you usually will not care about it, log it with a proper logging infrastructure (log4j, commons logging, or java.util.logging). that way it will most likely make it somewhere that you can see later if you decide that you actually do care about the exception after all.
On a recent project I recommended catching a RuntimeException within a test harness code and logging it. The code processes a series of inputs from a database, and I do not want the test to stop due to failure of any one input (Null values, Illegal arguments, etc.). Needless to say, my suggestion triggered a passionate discussion.
Is catching any kind of RuntimeException acceptable? If yes, what are other scenarios where it is OK to catch RuntimeExceptions?
You catch RuntimeException for the same reason that you catch any exception: You plan to do something with it. Perhaps you can correct whatever caused the exception. Perhaps you simply want to re-throw with a different exception type.
Catching and ignoring any exception, however, is extremely bad practice.
Unless you can correct a RuntimeException, you don't want to catch it...
...only true from a developers point of view....
you have to catch all exceptions before they reach up to the UI and make your user sad. This means on the "highest level" you want to catch anything that happend further down. Then you can let the user know there was a problem and at the same time take measures to inform the developers, like sending out alarm mails or whatever...
It is basically considered a data/programming error that could not be forseen, thus you want to improve future releases of the software while at the same time take the user by the hand and move on in a controlled manner...
RuntimeException is intended to be used for programmer errors. As such it should never be caught. There are a few cases where it should be:
you are calling code that comes from a 3rd party where you do not have control over when they throw exception. I would argue that you should do this on a case by case basis and wrap the usage of the 3rd party code within your own classes so you can pass back non-runtime exceptions.
your program cannot crash and leave a stack trace for the user to see. In this case it should go around main and around any threads and event handling code. The program should probably exit when such exception occurs as well.
In your specific case I would have to question why you are having RuntimeExceptions occur in the tests - you should be fixing them instead of working around them.
So you should guarantee that your code only throws RuntimeExceptions when you want to have the program exit. You should only catch RuntimeExceptions when you want to log it and exit. That is what is in line with the intent of RuntimeExceptions.
You can look at this discussion for some other reasons that people give... I personally haven't found a compelling reason in the answers though.
In my code 99% of my exceptions are derived from runtime_exception.
The reasons I catch exceptions are:
Catch Log and Fix problem.
Catch Log and Generate a more specific exception and throw
Catch Log and rethrow.
Catch Log and Kill operation (discard exception)
User/request initiated action fails.
An HTTP request handler for example. I would rather the requested operation die rather than bring the Service down. (Though preferably the handler has enough sense to return a 500 error code.)
Test case passed/failed with an exception.
All exceptions not in the main thread.
Allowing exceptions to escape a thread is usually badly documented but usually causes program termination (without stack unwinding).
Years ago, we wrote a control system framework and the Agent objects caught runtime exceptions, logged them if they could and continued.
Yes we caught Runtime exceptions including OutOfMemory in our framework code( and forced a GC, and it's surprising how well that kept even quite leaky code running.)
We had code that was doing very mathematical things involving the real world; and from time to time a Not-A-Number would get in due to tiny rounding errors and it coped okay with that too.
So in framework / "must not exit" code I think it can be justifiable. And when it works it's pretty cool.
The code was pretty solid, but it ran hardware, and hardware tends to give screwy answers sometimes.
It was designed to run without human intervention for months at a time.
It worked extremely well in our tests.
As part of the error recovery code, it could resort to rebooting the entire building using the UPS's ability to turn off in N minutes and turn on in M minutes.
Sometimes hardware faults need to power cycled :)
If I remember, the last resort after an unsuccessful power cycle was it sending an email to it's owners, saying
"I tried to fix myself and I can't; the problem is in subsystem XYZ", and included a link to raise a support call back to us.
Sadly the project got canned before it could become self aware :)>
Personally, I've always been told that you want to catch all RuntimeExceptions; however, you also want to do something about the exception, such as running a failsafe or possibly just informing the user that an error occurred.
The last Java project that I worked on had a similar approach, at the very least, we would log the exception so that if a user called complaining about a bug, we could find out exactly what happened and see where the error occurred.
Edit 1: As kdgregory said, catching and ignoring are two different things, generally, people are opposed to the latter :-)
We all know that checked exceptions and RuntimeExceptions are the two categories of exceptions. It is always suggested that we handle (either try-catch or throw) the checked exceptions because they are the programming conditions where unfortunately programmer can not to do anything on its own;
Like FileNotFoundException it is not the programmer who puts files on user's drive if program is actually trying to read the file 1.txt which is supposed to be there on f:\ of user with the statements:
File f11 = new File("f:\\1.txt");
FileInputStream fos = new FileInputStream(f11);
If the file is found it's all ok, but what happens in the other case if the file is not found is that, program crashes down with 0 error from the user. In this scenario programmer did not do anything wrong. This could be a checked exception which must be caught for the program to continue running.
Let me also explain the second scenario with which the concept of RuntimeException will be clear. Consider following code:
int a = {1,2,3,4,5};
System.out.println(a[9]);
This is poor coding which generates the ArrayIndexOutOfBoundsException. Which is an example of RuntimeException. So programmer should not actually handle the exception, let it crash the program, and later fix the logic.
You catch RuntimeException when you want to process it. Maybe you want to rethrow it as a different exception or log it to a file or database, or you want to turn on some exception flag in the return type, etc.
You catch RuntimeExceptions (in any language: unexpected exceptions/“all” exceptions) when your program is doing multiple subtasks and it makes sense to complete every one you can rather than stopping on the first unexpected situation. A test suite is a fine situation to do this — you want to know which of all the tests failed, not just the first test. The key characteristic is that each test is independent of all the others — it doesn't matter whether a previous test doesn't run because the order is not significant anyway.
Another common situation is a server; you don’t want to shut down just because one request was malformed in a way you didn't expect. (Unless it’s really, really important to minimize the chances of inconsistent state.)
In any of these situations, the appropriate thing to do is log/report the exception and continue with the remaining tasks.
One could vaguely generalize to any exception: it is “appropriate to catch” an exception if and only if there is something sensible to do after catching it: how your program should continue.
If a client can reasonably be expected to recover from an exception, make it a checked exception.
If a client cannot do anything to recover from the exception, make it an unchecked exception.
Here's the bottom line guideline.
From Java Docs. Please read this Unchecked Exceptions — The Controversy
I keep getting the dreaded java.something.someException errors while running my java app. and I don't seem to be getting the hang of what exceptions to handle and what not to?
When I read the api docs most of the functions throw exceptions like if I use I/O or use an Array... etc.
How to make a decision about what exceptions to catch and what not to and based on what parameters?
I am talking about checked exceptions here.
Short answer
Catch exceptions that you can deal with then and there, re-throw what you can't.
Long answer
It's called exception-handling code for a reason: whenever you are tempted to write a catch block, you need to have a good reason to catch the exception in the first place. A catch block is stating your intent to catch the exception, and then do something about it. Examples of doing something about it include, but are not limited to:
Retrying the operation that threw the exception. This can make sense in the case of IOException's and other issues that may be temporary (i.e. a network error in the middle of trying to upload a file to a server. Maybe your code should retry the upload a few times).
Logging the exception. Yes, logging counts as doing something. You might also want to re-throw the original exception after logging it so that other code still has a chance to deal with the exception, but that depends on the situation.
Wrapping the exception in another exception that is more appropriate for your class's interface. For example, if you have a FileUploader class, you could wrap IOException's in a more generic UploadFailedException so that classes using your class don't have to have detailed knowledge of how your upload code works (the fact that it throws an IOException is technically an implementation detail).
If the code can't reasonably do anything about the problem at the point where it occurs, then you shouldn't catch it at all.
Unfortunately, such hard-and-fast rules never work 100% of the time. Sometimes, a third-party library you are using will throw checked exceptions that you really don't care about or which will never actually happen. In these cases, you can get away with using an empty catch block that doesn't run any code, but this is not a recommended way to deal with exceptions. At the very least, you should add a comment explaining why you are ignoring the exception (but as CPerkins notes in the comments, "never say never". You may want to actually log these kinds of "never-going-to-happen" exceptions, so just in case such an exception does happen, you are aware of it and can investigate further).
Still, the general rule is, if the method you are in can't do something reasonable with an exception (log it, rethrow it, retry the operation, etc.) then you shouldn't write a catch block at all. Let the calling method deal with the exception. If you are dealing with checked exceptions, add the checked exception to the throws clause of your method, which tells the compiler to pass the exception upwards to the calling method, which may be better suited to handle the error (the calling method may have more context, so it might have a better idea of how to handle the exception).
Usually, it is good to put a try...catch in your main method, which will catch any exceptions that your code couldn't deal with, and report this information to the user and exit the application gracefully.
And finally, don't forget about finally
Also keep in mind that even if you don't write a catch block, you might still need to write a finally block, if you need clean-up code to run regardless of whether the operation you are trying to perform throws an exception or not. A common example is opening up a file in the try block: you'll still want to close the file, even if an exception occurs, and even if your method isn't going to catch the exception. In fact, another common rule of thumb that you might see in tutorials and books is that try...finally blocks should be more common that try...catch blocks in your code, precisely because catch blocks should only be written when you can actually handle the exception, but finally blocks are needed whenever your code needs to clean up after itself.
I highly recommend chapter 9 (Exceptions) in Joshua Bloch's Effective Java, 2nd Edition for these questions.
A general rule of thumb is to handle those exceptions that you can do something about and don't handle those that you can't. In the cases where you don't handle an exception the caller is expected to handle them. If you're writing a framework or a library usually you'll end up wrapping low level exceptions like SQLException in a library or framework specific exception to abstract away the lower level details.
For example, if you're writing a method that writes to a file on disk then you should probably handle FileNotFoundExceptions since you can create the missing file, but if you run into problems creating the file or writing to it then you should probably let the caller handle it (after performing whatever cleanup work needs to be done).
These are my personal findings:
You need a try {} catch (Throwable o) {...} in your main routine so any unexpected exception can be caught, logged and the user told.
Checked exceptions are checked because you need as a programmer to make a decision what to do when they happen. Remember, one decision might be just to say "ok, time to crash".
If you end up with a fatal situation with a checked exception where all you can do is crash, then "throw new RuntimeException("reason", checkedException);" so the handler above have something to log. Include value of important local variables - remember some day you will have to debug a situation where the only thing you have is the stack trace.
Never, ever catch an exception and just ignore it. If you have to then you must document why you are allowed to break the rule, and do it right there, in the catch block.
And a hint that will help you some day: When you crash, provide a simple means to let the user seeing the message email the stack trace to you.
EDIT: Do not be afraid to create new exceptions if the ones available does not completely cover what you need. This allows you to get better naming in stack traces and your error handling code can differentiate between different cases easily. You may want to base all your own exceptions on a common base class ("OurDomainException") so you can use the base class in catch clauses to see if what type it is.
Having coded in Java for a few years, I agree that it is easy to get annoyed by writing endless try-catch blocks.
A good way of coding fast is to catch specific exceptions in as low level as you can, and catch the base Exception at the outermost level (in main()) just so that you can write a generic error message instead of letting the program crash.
This lets you have a running code pretty fast, and then you can take your time to add specific exceptions in various layers with their handling logic.
Catch checked Exception, do not catch RuntimeException. Try to catch specific Exception, try not to catch by generic java.lang.Exception.
Module boundaries
I catch exceptions for cleaner module boundaries, too. For example if there is a SQLException thrown that I can't handle I'll catch it nevertheless and throw my own descriptive exception instead (putting the SQLException as cause). This way the caller doesn't have to know that I'm using a database to fulfill his request. He just gets an error "Cannot handle this specific use case". If I decide to fulfill his request without database access, I don't have to change my API.
As a rule of thumb I catch exceptions where I will be able to do something with then, or where I want the exception to stop moving up. For example, if I am processing a list of items, and I want the next item to be processed even if the others fail, then I will put a try...catch block around that item processing and only in there. I usually put a try...catch(Throwable) in the main method of my program so I can log errors like a class not found or similar stuff.
I don't put a try...catch block in a method if I will not know what to do with that exception. If you do, you will just bloat your code with lots of exception handling code.