I do, but no, exceptions aren't equivalent.

Erlang has the idea of exceptions. You can explicitly throw them, as well as certain situations generating them. They can be caught, using the familiar try/catch paradigm (well, somewhat familiar; it's used a little differently, with a slightly different syntax, but basically the same purpose).

It also has the idea of an exit signal, which will kill a process regardless (unless that process is trapping exit signals, because you want to do something prior to exiting, or prevent it, or whathaveyou).

A crash is what happens when you don't catch the exception/exit. Same as in other languages. -But-, in Erlang, it only kills the lightweight process (the term 'green process' has been used, akin to a green thread, except no state is shared between them), rather than taking down the VM.

In Java/etc, when you have an exception, if you don't catch it, it percolates back up the stack to the top and takes down your application; the execution of -everything- is ended. You might have a watcher process that restarts the app, but you took out the whole app. In the event of an unexpected exception, then, you either killed the app, or have a catch(Exception) somewhere, which is widely viewed as an antipattern, and which you really don't know how to recover from.

In Erlang, when you have an exception, if you don't catch it, it merely kills the (green) process, which if not intended to be ephemeral, should be supervised, linked to any process it implicitly shares state with (linking causes a dying process to send out exit signals to the linked process, so they die and restart too) and have a well written initialization step that will read from any persisted 'good' state, and bring it back to that state. So you get back into a good state having only taken down the bit that actually went wrong, rather than everything. The other processes are unaffected; no memory was shared between them, so they can continue on their merry way. They might have been expecting a message from the process that died, but if so, they'll be waiting on a timeout, and should either retry sending it, or themselves die and restart (message passing makes no guarantee of delivery, so you have to deal with the possibility that messages won't arrive; this is really, really useful in distributed scenarios, as it means there is no difference in sending a message locally, and sending a message remotely).

In the Java case, you try your best not to let exceptions go uncaught, because the user experience is terrible if you do. But it's easy to miss things that can cause exceptions. And when you catch them, it may not be clear what to do with them anyway, so you end up writing a bunch of error handling code runs the risk of keeping you in a bad ambiguous state, that leads to hard to debug issues further down the line.

In the Erlang case, you treat everything as being able to die at any time, making sure your supervisor hierarchy is sensible, and making sure every process reinitializes properly in the event of its death. After that, you worry about catching only those exceptions you expect to happen and have a well defined way of dealing with (which is usually very few); any other causes the state to be dropped and that process to be restarted. You get a log of it, you can decide you want to explicitly handle that case, because recovery from it is well defined, or you can just shrug and move on because it truly was just a hiccup, and you don't need to address it; either way, the process is back in a good state, and the system is able to continue along with barely a blip.

EDIT: A few links to help explain it (as it's a different programming model than Java/C++/Python/etc, and understanding how the philosophy applies requires understanding the model) -

http://www.slideshare.net/dnene/actors-fault-tolerance-and-o...

http://stackoverflow.com/questions/3172542/are-erlang-otp-me...