Using exceptions for early exit

I ran across the following article on Java exceptions and noticed this
little tidbit:

"Sometimes developers decide to use exception for flow-control (i.e. to
throw an exception once a certain condition is met). The generation of
stack-traces is expensive and developers should realise that an
exception should only be used in exceptional cases."

(1) is this still true? Is a stack trace still expensive?
(2) do all exceptions do this? For example, if I just inherit from
"Throwable" rather than "Exception" is a stack trace still generated?
(3) is there any way around this?

The reason I'm asking is that exceptions would seem to be a very good
way to implement early-exit from certain deeply-nested computations.

Advertisements

Jonathan Bartlett <> wrote:
> "Sometimes developers decide to use exception for flow-control (i.e. to
> throw an exception once a certain condition is met). The generation of
> stack-traces is expensive and developers should realise that an
> exception should only be used in exceptional cases."
>
> (From http://javafoundry.ibscon.com/content/view/18/ )
>
> A few questions:
>
> (1) is this still true? Is a stack trace still expensive?

Yes, it's still true that generating a stack trace is a relatively
expensive operation, compared to other methods of accomplishing this.
Whether that justifies the generalization above is a different matter.
The number of situations in which small performance costs matters enough
to justify making your life harder is actually rather small.

On the other hand, just from a readability standpoint, use of exceptions
for minor flow control purposes is a poor idea. The ultimate test is
whether there is a substantial body of code in which the exception
actually makes sense and can be given a simple descriptive name.
Generally, when exceptions do get used, there is some context in which
is really IS an exceptional case. Exceptional, in the context of Java,
doesn't mean that it almost never happens, but rather than the code to
handle it is not relevant to the purpose of the method you're writing.
> (2) do all exceptions do this? For example, if I just inherit from
> "Throwable" rather than "Exception" is a stack trace still generated?
> (3) is there any way around this?

Advertisements

Jonathan Bartlett wrote On 12/12/05 09:57,:
> I ran across the following article on Java exceptions and noticed this
> little tidbit:
>
> "Sometimes developers decide to use exception for flow-control (i.e. to
> throw an exception once a certain condition is met). The generation of
> stack-traces is expensive and developers should realise that an
> exception should only be used in exceptional cases."
>
> (From http://javafoundry.ibscon.com/content/view/18/ )
>
> A few questions:
>
> (1) is this still true? Is a stack trace still expensive?
> (2) do all exceptions do this? For example, if I just inherit from
> "Throwable" rather than "Exception" is a stack trace still generated?
> (3) is there any way around this?
>
> The reason I'm asking is that exceptions would seem to be a very good
> way to implement early-exit from certain deeply-nested computations.

The first two seem the sort of questions you could
answer for yourself with a little experimentation. You'd
get not only answers, but quantitative answers.

The third is unclear to me. What is the "this" you're
worried about, and what would it mean to get "around" it?
That is, what is your problem and what are your criteria
for a successful solution?

Jonathan Bartlett wrote:
> The reason I'm asking is that exceptions would seem to be a very good
> way to implement early-exit from certain deeply-nested computations.

If this is your need that probably means that you have to change your
code (for example, you can make methods out of your computations).
If you don't, have a look at break and continue. I personally never use
them (I consider them mostly an extreme solution), but that's what they
are for

> If this is your need that probably means that you have to change your
> code (for example, you can make methods out of your computations).
> If you don't, have a look at break and continue. I personally never use
> them (I consider them mostly an extreme solution), but that's what they
> are for

I was actually looking for a means of a quick escape from
deeply-recursive functions. Just throw the exception to exit the recursion.

Jonathan Bartlett wrote On 12/12/05 14:02,:
>> The third is unclear to me. What is the "this" you're
>>worried about, and what would it mean to get "around" it?
>
>
> Producing stack traces.
>
>
>>That is, what is your problem and what are your criteria
>>for a successful solution?
>
>
> Throw something that didn't generate a stack trace.

As far as I know, every Throwable contains a stack
trace. You don't need to display it, but it'll be there
no matter what you do.

However, the stack trace is built when the Throwable
is constructed, not by the "throw" action. You could
therefore construct your Exception once at class-loading
time, and then throw the same Exception object as often
as you like:

Guest

Jonathan Bartlett wrote:
>
> "Sometimes developers decide to use exception for flow-control (i.e. to
> throw an exception once a certain condition is met). The generation of
> stack-traces is expensive and developers should realise that an
> exception should only be used in exceptional cases."
>
> (From http://javafoundry.ibscon.com/content/view/18/ )
>
> A few questions:
>
> (1) is this still true? Is a stack trace still expensive?

That article is less than two years old. Yes, it appears to still be
true. It is apparently something not considered worth spending time on
optimising. IIRC, I measured around ten or twenty thousand cycles with a
shallow stack. The bigger the stack, the more work to do.
> (2) do all exceptions do this? For example, if I just inherit from
> "Throwable" rather than "Exception" is a stack trace still generated?

UTSL. If you look at the source to Throwable, you can see it calling
fillInStackTrace.
> (3) is there any way around this?

Override fillInStackTrace or use the same exception over again.

I timed 1.5 (or 1.4?) with -server in a loop catching an exception
thrown through an interface. The benchmark got optimised away.
> The reason I'm asking is that exceptions would seem to be a very good
> way to implement early-exit from certain deeply-nested computations.

Probably not a good idea. Labeled break is good within the same method.
You can probably rearrange the algorithm to make the exception unnecessary.

In my years of Java programming I have never (seriously) used an
exception that way. Mind you when I write recursive code, I tend to
rewrite it properly before the first compile.

wrote:
> All recursive operations can be written as iterative. If stack
> unwinding irritates you, feel free to rewrite this algorithm to use
> iteration.

Having spent the better part of two days recently rewriting a deeply recursive
algorithm into a pure (no local variables) iterative formulation, and /NEVER/
wanting to do so again, I cannot but feel that this poor advice...

Just curious. If the Java language had a non-local-return feature, with
appropriate syntax, and semantics that was (at worst) no harder to get right
than throwing an exception (i.e. /not/ C's setjmp()/longjmp()), would you still
feel the same way ?

Is the issue the "shape" of the control-flow or the syntax used to express it ?

(For me it's the latter -- I don't like the idiom either, but that's because I
would expect that people reading the code would /not/ expect exceptions to be
used in that way; I have no problems with a precisely controlled, but
non-local, flow of control in itself. Which, come to think of it, is just as
well since I don't object to exceptions...)

On Mon, 12 Dec 2005 08:57:39 -0600, Jonathan Bartlett
<> wrote, quoted or indirectly quoted someone who
said :
>(1) is this still true? Is a stack trace still expensive?

Every time an exception is thrown the raw data to print a stack trace
has to be collected from the stack, interpretively wending its way
from top to bottom. It has to collect it before the exception
destroys the stack popping in off seeking a handler. There is even
more data collected that typically printed. seehttp://mindprod.com/jgloss/trace.html

It takes several orders of magnitude more time that a simple flow of
control jump. Don't use exceptions for exceptional conditions.

I discovered that way back in 1969 when I decided to use PL/I ON units
for flow control, just to experiment. I could not believe how slow it
was.

On Mon, 12 Dec 2005 14:56:52 -0500, Eric Sosman <>
wrote, quoted or indirectly quoted someone who said :
> However, the stack trace is built when the Throwable
>is constructed, not by the "throw" action. You could
>therefore construct your Exception once at class-loading
>time, and then throw the same Exception object as often
>as you like:

On Mon, 12 Dec 2005 21:02:39 -0000, "Chris Uppal"
<-THIS.org> wrote, quoted or indirectly
quoted someone who said :
> If the Java language had a non-local-return feature, with
>appropriate syntax, and semantics that was (at worst) no harder to get right
>than throwing an exception (i.e. /not/ C's setjmp()/longjmp()), would you still
>feel the same way ?

I invented such tools in my BBL and Abundance language. I used them
only for constructing early return verbs, not for jumping up many
levels.

Chris Uppal wrote On 12/12/05 16:02,:
> Eric Sosman wrote:
>
>
>>class Perverse {
>
>
>> public void somethingStupid(int n) throws Exception {
>
>
>> public void moreStupidity(double p) throws Exception {
>
>
>
> Just curious. If the Java language had a non-local-return feature, with
> appropriate syntax, and semantics that was (at worst) no harder to get right
> than throwing an exception (i.e. /not/ C's setjmp()/longjmp()), would you still
> feel the same way ?
>
> Is the issue the "shape" of the control-flow or the syntax used to express it ?
>
> (For me it's the latter -- I don't like the idiom either, but that's because I
> would expect that people reading the code would /not/ expect exceptions to be
> used in that way; I have no problems with a precisely controlled, but
> non-local, flow of control in itself. Which, come to think of it, is just as
> well since I don't object to exceptions...)

The syntax doesn't bother me much, although there's a
certain amount of clumsiness about try/catch/finally. The
fact that each of the three blocks has its own scope means
that there's no single scope for the entire construct; this
makes me declare variables at a scope wider than they really
ought to have, or introduce an extra level of { } simply to
create a containing scope. And it's irritating to catch an
IOException, say, and then put yet another try/catch inside
the finally that closes the BufferedReader or whatever. But
these are just cosmetic issues, nothing I can't live with.

Nor is the shape of the control flow a problem. The route
taken by a Java exception has the right balance of unpredictable
(the thrower doesn't know the catcher) and predictable (the
catcher will necessarily be an active call frame). A goto style
(e.g., PL/I or Pascal) loses the flexibility of "anonymous" (or
else requires label variables, which are hard to validate), while
the trust-the-programmer style of C's longjmp() all too often
engenders really horrible bugs. Java exceptions unwind in a
calm and orderly fashion, which I find soothing.

My objections to control-flow-by-exception are twofold.
First, there's efficiency. Yes, I know it's unfashionable
to talk about efficiency, but those of us who programmed in
Olden Times formed the hard-to-shake habit of keeping it in
mind. I'm still an efficiency addict (on, er, method-done
treatment ;-), and cannot help but think of all the cycles
that must be spent on a throw/catch. Even if you pre-construct
the thrown exception, the JVM still needs to conduct a possibly
lengthy search up the stack to find candidate catch blocks; a
chain of returns -- even if a method result must be if'ed at
each level -- will almost certainly be faster.

My other objection is a "right job, wrong tool" feeling.
Sure, it's possible to use exceptions for control flow, but
Java's control flow constructs are there because they're more
convenient, more readable, and better suited to the task. One
can replace a "switch" with a try/catch/catch/catch/catch...
block, but that doesn't mean one ought to. Exceptions should
be, well, exceptional -- they're not called Normals, after all!
I like to think of a method as having a contract that in normal
circumstances is "contained" in its arguments, its returned
value, and the states of the objects it touches. When I call
the method, I want it to return with its contract fulfilled.
Exceptions are for when there's something that prevents the
method from fulfilling its contract: invalid arguments or state,
I/O errors, whatever.

On 12 Dec 2005 10:27:00 -0800, ""
<> wrote, quoted or indirectly quoted someone
who said :
>A particular example in the API of using exceptions for flow control is
>Integer.parseInt. There's no way of asking whether the int is
>parseable,so you have to detect it via an exception.

that requires you to deal with errors at every use. With Exceptions
you can deal with them all in one place, e.g. if your numbers are
supposed to be generated by some other computer in perfect form where
even one being wrong indicates a program bug.
--
Canadian Mind Products, Roedy Green.http://mindprod.com Java custom programming, consulting and coaching.

On Mon, 12 Dec 2005 13:04:37 -0600, Jonathan Bartlett
<> wrote, quoted or indirectly quoted someone who
said :
>I was actually looking for a means of a quick escape from
>deeply-recursive functions. Just throw the exception to exit the recursion.

Even if you did, it would not be quick. An exception interpretively
combs the stack looking for a handler. Conceptually it looks as though
it pops the stack in one fell swoop, but if you benchmark the code I
think you will find it faster to just return recursively.

You might enjoy Abundance which has a feature to jaunt( leap backward
in time to a previous execution checkpoint). It does that very rapidly
by copying a stack snapshot in as the real one and restoring a few
crucial system variables.
--
Canadian Mind Products, Roedy Green.http://mindprod.com Java custom programming, consulting and coaching.

Share This Page

Welcome to The Coding Forums!

Welcome to the Coding Forums, the place to chat about anything related to programming and coding languages.

Please join our friendly community by clicking the button below - it only takes a few seconds and is totally free. You'll be able to ask questions about coding or chat with the community and help others.
Sign up now!