Win a copy of Terraform in Action this week in the Cloud forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • Paul Clapham
  • Ron McLeod
  • Liutauras Vilda
Sheriffs:
  • Jeanne Boyarsky
  • Rob Spoor
  • Bear Bibeault
Saloon Keepers:
  • Jesse Silverman
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
Bartenders:
  • Piet Souris
  • Al Hobbs
  • salvin francis

exception and getCause()

 
Ranch Hand
Posts: 375
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sometimes we wrap an original Exception A into Exception type B, and wrap Exception type B into type C, etc. We can use

e.getCause().getClass() to find out what's the original "caused by" exception. But since the original Exception has been wrapped for a few times, how do we know the very first "caused by" exception. When you code you don't know how many times you need to do "getcause().getCause()...". So is there a quick handy API to retrieve the original exception class ?
 
Sheriff
Posts: 22510
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Use a loop until getCause() returns null. Once that's the case you've found the root cause.
 
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Spoor wrote:Use a loop until getCause() returns null. Once that's the case you've found the root cause.



Technically you've just found the deepest level where an exception was thrown without wrapping another exception. In a perfect world, that's the root cause, but there's no guarantee somebody didn't forget to wrap an underlying exception, or just choose not to for whatever reason.

 
Rob Spoor
Sheriff
Posts: 22510
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
But if that's the case then it's impossible to get the root.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Spoor wrote:But if that's the case then it's impossible to get the root.



Right.

I was just trying to make the point to take with a grain of salt the idea that "deepest one I can see" is the same as "root cause". In most cases, it should be, but when you get to that oddball case where what you're seeing just doesn't make sense, it's good to keep in mind that it is possible to truncate the stack trace at the knees.
 
Marshal
Posts: 26914
82
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
And to indulge in even wilder speculation, it looks like it's possible to put infinite loops into the chain of Exception causes:

Although I haven't tried this to see whether it's actually forbidden in some way; the documentation doesn't appear to forbid that code.
 
Greenhorn
Posts: 14
Eclipse IDE VI Editor BSD
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Paul Clapham wrote:And to indulge in even wilder speculation, it looks like it's possible to put infinite loops into the chain of Exception causes:

Although I haven't tried this to see whether it's actually forbidden in some way; the documentation doesn't appear to forbid that code.



No, that's not possible the initCause throws an IllegalArgumentException, that's documented in Throwable#initCause







 
ben oliver
Ranch Hand
Posts: 375
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Spoor wrote:Use a loop until getCause() returns null. Once that's the case you've found the root cause.



Rob, is it possible that this may end up with infinite loop ? assuming programmer only wrap the exception for 3 times, are you sure keep doing getCause() will always end with returning null ? please clarify, thanks
 
Master Rancher
Posts: 4062
56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Andi- it's true that simple self-causation is prohibited. But it's still possible to get an infinite loop:
 
Rob Spoor
Sheriff
Posts: 22510
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hmm, that's actually quite bad of Sun / Oracle to not prevent that. yang.initCause(yin) should throw an IllegalArgumentException because yang is already an ancestor cause of yin. So yes Ben, that code could cause an infinite loop. One that should never occur unless someone's being malicious on purpose or doesn't have a clue what he's doing.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Spoor wrote:Hmm, that's actually quite bad of Sun / Oracle to not prevent that. yang.initCause(yin) should throw an IllegalArgumentException because yang is already an ancestor cause of yin.



I think it's actually a reasonable decision. To add a test for a duplicate in an arbitrarily deep stack would increase the memory usage and/or complexity of the exception handling mechanism. I'd think that would be something we'd want to keep as tight and simple as possible, and I can see why it wouldn't be considered worth it for a situation that should never arise in the first place.

JMHO.
 
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One way they could have done it without that impact was to only allow the cause to be initialised in the constructor. I don't know if the cost in loss of flexibility would be worth it...I can't remember doing anything other than setting it on construction in my own code but there may be cases it would be useful to do it later.
 
Mike Simmons
Master Rancher
Posts: 4062
56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Initially I too thought it might be too expensive - but on reflection, I don't think it is.

That should be pretty quick, really - how many nested causes are there, typically? Up to four or five is not uncommon in my experience, but it should be quite rare that it ever exceeds, say, ten. So the cost should be small compared to the rest of creating an exception. As long as that same initCause() is also called by any constructor that sets a cause (which it is), no cycles should be possible here, right?

Now Sun probably never would have gone for this because it might "break" the existing API of initCause(). Oh well. Oracle might be more willing to fix it, however.
 
Mike Simmons
Master Rancher
Posts: 4062
56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have used initCause() just a few times, mostly for IOException I think - they never added a constructor there that takes a cause, so you need initCause() to initialize the cause for any exception class that wasn't fully retrofitted when they added nested exceptions.
 
Rob Spoor
Sheriff
Posts: 22510
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Mike Simmons wrote:I have used initCause() just a few times, mostly for IOException I think - they never added a constructor there that takes a cause, so you need initCause() to initialize the cause for any exception class that wasn't fully retrofitted when they added nested exceptions.


Those constructors were added in Java 6. When I was still using Java 1.4 I had two utility methods to thow IOExceptions based on a message (or not) and the cause. As soon as Java 6 came out, those two methods were deprecated.
 
Mike Simmons
Master Rancher
Posts: 4062
56
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Spoor wrote:Those constructors were added in Java 6.


Ah, good to know, thanks.
 
Rob Spoor
Sheriff
Posts: 22510
122
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You're welcome.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic