Reputation: 8395
I am having a piece of code and in the catch block I intentionally add some piece of code as I am sure the flow will once come to catch. So for a big project, is this type of coding leads to some more resource usage as logically if any exception occurs, lead to a new thread or hold in JVM so it means some resource utilization and I do have a way to avoid exception to occur and do the piece of code somewhere in proper place.
Let me clarify-
char ch = 'c'
try{
Integer.parse(character.toString(ch));
}(Exception e){
//SOME VERY IMPORTANT OPERATION LIKE LOGIC MATHEMATICAL BASED
}
Now the above piece of code will throw me NumberFormatException and inside the catch loop I added my piece of logic, Now the same thing I can avoid and write
char ch = 'c';
if(!Character.isDigit(ch))
//SOME VERY IMPORTANT OPERATION LIKE LOGIC MATHEMATICAL BASED
Now I didn't write any exception but it will work properly.
Now my question, is the 1st approach of catch coding will lead to some internal resource usage , I mean does JVM internally leads to some internal resource usage and this kind of catch coding should be avoided as max as possible or I can definately use the 1st approach
Upvotes: 1
Views: 2754
Reputation: 718906
Lets talk about what is expensive about exceptions and exception handling.
First thing to observe is that try / catch costs almost nothing if an exception doesn't occur. At most, there might be an extra branch instruction to jump over a block of code that implements handlers, and I would expect that the JIT compiler would normally order the code blocks to avoid that.
Throwing, propagating and handling exceptions is a bit more expensive, but not a great deal. I don't have any real numbers, but I suspect that we are only talking about tens of instructions for each of these.
The really expensive part of exception handling in Java is creating and initializing the exception object prior to throwing it. And the expense occurs because the exception needs to capture and record the information that later will be output in the stacktrace. And, the cost is proportional to the stack depth at the point where the exception object is created (and typically also thrown).
The bottom line is that the total cost of creating, throwing, propagating an exception is typically thousands of instructions. Hence the Java proverb that exceptions should only be used for exceptional conditions.
So what does that really mean in practical terms.
Lets take a look at an example similar to yours:
public int toInt(String str, int dflt) {
try {
return Integer.parse(str);
} (NumberFormatException e) {
return dflt;
}
}
private static final Pattern numberPattern = Pattern.compile("-?\\d+");
public int toInt(String str, int dflt) {
if (numberPattern.matcher(str).matches()) {
return Integer.parse(str);
} else {
return dflt;
}
}
Two versions. One lets the exception happen and catches it, and the other does some non-trivial checking to avoid throwing the exception in the first place.
Which is more efficient? Well it depends on the probability that the method is called with an invalid number. For instance, if the invalid numbers occur once in 1,000 calls, then 999 in 1,000 times the second version applies the regex unnecessarily to avoid the 1 case where the exception is thrown; i.e. the first version is on average faster. On the other hand, if invalid numbers occur 1 time in 2, then we are comparing the cost of 2 calls to the regex engine versus one exception created, thrown and caught. And my money is on the second version being significantly faster on average.
To generalize, a decision based purely on performance boils down to some simple math. If p
is the probability that the exception would occur, A
is the average cost of the test to avoid the exception, and E
is the average cost of create/throw/catch, then you need to compare p * E
with (1 - p) * A
. If the first is smaller then let the exception happen, and if the second is smaller, avoid the exception.
Of course, getting accurate values or estimates for p
, A
and E
is difficult. So a more practical approach is to go with your gut feeling to start with ... and then profile your application to see there is any need to optimize.
Upvotes: 1
Reputation: 16235
It is not a good practice to rely on Exceptions for normal program flow.
If I understand your question, it sounds like your code is relying on Exceptions for normal flow - i.e. you expect to enter catch
blocks routinely.
This is not a good way to code and certainly uses more resources than code which avoids avoidable Exceptions from being thrown (e.g. using state checking methods with if/else
rather than relying solely on try/catch
).
Coding with try/catch is not inefficient. Code which routinely generates loads of Exceptions and uses them for normal control flow is not efficient.
Upvotes: 0
Reputation: 1074495
It's very hard to understand the question, but some general points:
Exceptions are for exceptional events. Exceptions should not be used for normal conditions. Throwing an exception is an expensive operation.
try/catch/finally
blocks are not resource-expensive at all. JVMs are optimized to handle them very efficiently, because properly-written code uses them all over the place.
The cost comes in when an exception occurs, not when you use try/catch/finally
in your code. So you should feel free to use try/catch/finally
all over the place, but avoid writing code that relies on exceptions in the normal course of things.
For instance, here's a bad example of using exceptions:
/**
* Gets a `Thingy` instance based on the given `Foo`.
*
* @param foo the `Foo`, or `null`
* @return the new `Thingy` based on the given `Foo`, or `null` if `foo`
* is `null`
* @throws ThingyException if no `Thingy` can be constructed for the given `Foo`
*/
Thingy getThingyForFoo(Foo foo) {
throws ThingyException
ExpensiveThingyFactory factory = getExpensiveThingyFactory();
try {
return factory.getThingy(foo);
}
catch (NullPointerException npe) {
return null;
}
finally {
factory.release();
}
}
This is bad because the method clearly says that passing in a null
foo
argument is a normal use case, but the code relies on factory.getThingy(foo)
throwing a NullPointerException
when you pass in foo = null
. Since that's a documented normal use-case, you code for it explicitly:
/**
* Gets a `Thingy` instance based on the given `Foo`.
*
* @param foo the `Foo`, or `null`
* @return the new `Thingy` based on the given `Foo`, or `null` if `foo`
* is `null`
* @throws ThingyException if no `Thingy` can be constructed for the given `Foo`
*/
Thingy getThingyForFoo(Foo foo) {
throws ThingyException
ExpensiveThingyFactory factory = null;
if (foo == null) {
return null;
}
factory = getExpensiveThingyFactory();
try {
return factory.getThingy(foo);
}
finally {
factory.release();
}
}
The try/finally
in that is not expensive. Throwing an exception is expensive.
Upvotes: 4
Reputation: 47729
There is execution overhead in using a catch block, or even having a try/catch, for that matter. But the overhead is due to breaking optimization of the generated code, and may amount to a few dozen extra machine instruction (plus, of course, the cost of handling the exception itself).
But the code in the catch block is executed in the same thread as the main routine, and uses the same auto stack frame, and, other than internal locks used during exception handling, no additional "resources" are used -- the only new object is the exception itself, there are no locks held while executing the catch
, no major change in storage footprint, etc.
Upvotes: 0
Reputation: 15879
I answer this question assuming basic Java usage is being questioned.
No, code in a catch
block will not behave any differently to code written anywhere else. If you are creating "new" objects inside your catch block then more resource will be used, but this is not different from a "new" object being created anywhere else.
The JVM will not create objects before they are specified in the code. So if your catch
block is not executed no additional resource is required.
Catch
blocks also execute on the same thread as the Try
block. That is why e.printStackTrace()
is able to show you what has been executing
Upvotes: 0
Reputation: 1891
I do not think much overhead is incurred in having a try catch block, but when exception is raise there is an over head of unwinding the stack until the matching catch block is found.
If the exception does not occur there is not penalty.
Upvotes: 1