Using exceptions for early exit

Discussion in 'Java' started by Jonathan Bartlett, Dec 12, 2005.

  1. 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.

    Jon
    ----
    Learn to program using Linux assembly language
    http://www.cafeshops.com/bartlettpublish.8640017
    Jonathan Bartlett, Dec 12, 2005
    #1
    1. Advertising

  2. Jonathan Bartlett

    Chris Smith 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?


    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?


    Yes, and no.

    --
    www.designacourse.com
    The Easiest Way To Train Anyone... Anywhere.

    Chris Smith - Lead Software Developer/Technical Trainer
    MindIQ Corporation
    Chris Smith, Dec 12, 2005
    #2
    1. Advertising

  3. Jonathan Bartlett

    Eric Sosman Guest

    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?

    --
    Eric Sosman, Dec 12, 2005
    #3
  4. 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
    Andrea Desole, Dec 12, 2005
    #4
  5. Jonathan Bartlett

    Guest

    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.

    I think it would be better like this:

    IntegerParseResult result=Integer.parseInt("5556");

    if (result.hasValue())
    doStuff(result.getValue());
    else
    handleTheBadStuff();

    getValue() would throw an IllegalStateException ifcalled when
    !result.hasValue().
    , Dec 12, 2005
    #5

  6. > 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.

    Jon
    Jonathan Bartlett, Dec 12, 2005
    #6
  7. > 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.

    Jon
    Jonathan Bartlett, Dec 12, 2005
    #7
  8. Jonathan Bartlett

    Eric Sosman Guest

    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:

    class Perverse {

    private static Exception perverseException
    = new Exception();

    public void somethingStupid(int n) throws Exception {
    if (n <= 0)
    throw perverseException;
    else
    somethingStupid(n-1);
    }

    public void moreStupidity(double p) throws Exception {
    if (Math.random() < p)
    throw perverseException;
    }
    }

    Thus, you'd only incur the cost of creating and initializing
    the Exception once, instead of at every throw.

    I won't reveal what I think about the advisability of the
    technique, but the names in the illustration above may provide
    a tiny clue ... Have I just given a loaded pistol to a child?

    --
    Eric Sosman, Dec 12, 2005
    #8
  9. Jonathan Bartlett

    Oliver Wong Guest

    "Jonathan Bartlett" <> wrote in message
    news:439dc9c4$...
    >
    > I was actually looking for a means of a quick escape from deeply-recursive
    > functions. Just throw the exception to exit the recursion.


    This sounds like a "Bad Idea".

    Does your recursive function return a value? Does it modify some other
    data structure? You might be able to "get out of the recursion" more cleanly
    by using a "return" statement.

    - Oliver
    Oliver Wong, Dec 12, 2005
    #9
  10. Jonathan Bartlett

    Guest

    All recursive operations can be written as iterative. If stack
    unwinding irritates you, feel free to rewrite this algorithm to use
    iteration.
    , Dec 12, 2005
    #10
  11. 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.

    Tom Hawtin
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
    Thomas Hawtin, Dec 12, 2005
    #11
  12. Jonathan Bartlett

    Chris Uppal Guest

    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...

    -- chris
    Chris Uppal, Dec 12, 2005
    #12
  13. Jonathan Bartlett

    Chris Uppal Guest

    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...)

    -- chris
    Chris Uppal, Dec 12, 2005
    #13
  14. Jonathan Bartlett

    Roedy Green Guest

    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. see
    http://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.


    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Java custom programming, consulting and coaching.
    Roedy Green, Dec 12, 2005
    #14
  15. Jonathan Bartlett

    Roedy Green Guest

    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:


    I'm have added your technique to the pantheon at
    http://mindprod.com/jgloss/unmainobfuscation.html
    point number 19.
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Java custom programming, consulting and coaching.
    Roedy Green, Dec 12, 2005
    #15
  16. Jonathan Bartlett

    Guest

    Chris,

    Just because changing a recursive implementation into an iterative
    implementation is awkward, doesn't mean that the iterative version is
    wrong, or that it is bad advice to suggest to do so.

    If the poster had written in an iterative way originally then I don't
    think there'd be an issue.

    I know from my own experience that changing recursive to iterative can
    be a real pain, I've done it for something non-trivial.

    I've never heard of this 'pure iterative' concept before, so I'm unsure
    why you would aim to have no local variables. I've probably
    misunderstood.
    , Dec 12, 2005
    #16
  17. Jonathan Bartlett

    Roedy Green Guest

    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.

    e.g. for example in Abundance you can say

    aBoolean ?EXIT>>>

    instead of

    aBoolean IF EXIT>>> THEN

    or

    aBoolean ?YES>>>

    instead of

    aBoolean IF YES EXIT>>> THEN

    (returns value yes if true, otherwise carries on)

    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Java custom programming, consulting and coaching.
    Roedy Green, Dec 12, 2005
    #17
  18. Jonathan Bartlett

    Eric Sosman Guest

    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.

    So: My objections amount to an old-fashioned concern for
    efficiency combined with a Puritanical fastidiousness. Neither
    is binding on anyone else; follow your weird.

    --
    Eric Sosman, Dec 12, 2005
    #18
  19. Jonathan Bartlett

    Roedy Green Guest

    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.
    Roedy Green, Dec 12, 2005
    #19
  20. Jonathan Bartlett

    Roedy Green Guest

    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.
    Roedy Green, Dec 12, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Marc Miles

    Exit Custom Server Control Early

    Marc Miles, Aug 16, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    347
    Marc Miles
    Aug 17, 2005
  2. Joe Smith
    Replies:
    4
    Views:
    65,794
    sandeep1976
    Nov 8, 2006
  3. gcash
    Replies:
    0
    Views:
    455
    gcash
    Feb 20, 2004
  4. Sara

    A non-loop block early exit?

    Sara, Feb 10, 2004, in forum: Perl Misc
    Replies:
    4
    Views:
    104
    David K. Wall
    Feb 10, 2004
  5. Rob

    Function seems to exit early

    Rob, Mar 16, 2007, in forum: Javascript
    Replies:
    2
    Views:
    102
Loading...

Share This Page